source: trunk/Cbc/examples/parallel.cpp

Last change on this file was 1998, checked in by forrest, 5 years ago

for threadsafe

File size: 7.1 KB
Line 
1// $Id: parallel.cpp 1902 2013-04-10 16:58:16Z stefan $
2// Copyright (C) 2007, International Business Machines
3// Corporation and others.  All Rights Reserved.
4// This code is licensed under the terms of the Eclipse Public License (EPL).
5
6#include <cassert>
7#include <iomanip>
8
9
10#include "CoinPragma.hpp"
11#include "CbcModel.hpp"
12#include "OsiClpSolverInterface.hpp"
13#include "CbcSolver.hpp"
14
15#include "CoinTime.hpp"
16
17//#############################################################################
18
19
20/************************************************************************
21
22This main program shows how to take advantage of the standalone cbc in your program,
23while still making major modifications.
24This is like driver4 but executes in parallel
25First it reads in a model from an mps file
26Then it initializes three integer models with cbc defaults
27Then it calls CbcMain0/1 using threads passing parameters
28Finally it prints solution (just for first model)
29
30All models have same parameters unless "-switch" is found so --
31
32miplib/p0033 -solve -switch -heuristic off -solve
33
34would solve first model with heuristics and subsequent ones without
35
36This could be used to try different ideas OR on different models
37
38NOTE -
39The minimum has been done to make thread safe so
40no interrupts
41-quit is added to make sure just reads from argv
42*/
43/*************************************************************************/
44#define USE_PTHREAD
45#ifdef USE_PTHREAD
46#include <pthread.h>
47#endif
48/* Return non-zero to return quickly */   
49static int callBack(CbcModel * model, int whereFrom)
50{
51  int returnCode=0;
52  switch (whereFrom) {
53  case 1:
54  case 2:
55    if (!model->status()&&model->secondaryStatus())
56      returnCode=1;
57    break;
58  case 3:
59    {
60      //CbcCompareUser compare;
61      //model->setNodeComparison(compare);
62    }
63    break;
64  case 4:
65    // If not good enough could skip postprocessing
66    break;
67  case 5:
68    break;
69  default:
70    abort();
71  }
72  return returnCode;
73}
74// For threads
75typedef struct {
76  CbcModel * model;
77  CbcSolverUsefulData * data;
78  int argc;
79  char ** argv;
80} threadStuff;
81static void * doThread(void * voidInfo)
82{
83  threadStuff * stuff = reinterpret_cast<threadStuff *>(voidInfo);
84  CbcModel * model = stuff->model;
85  CbcMain0(*model,*stuff->data);
86  // Now go into code for standalone solver
87  CbcMain1(stuff->argc,const_cast<const char **>(stuff->argv),
88           *model,callBack,*stuff->data);
89  return NULL;
90}
91int main (int argc, const char *argv[])
92{
93  // Number of models to do at once
94  int numberModels=3;
95  // Stuff for each model
96  CbcModel * allModels = new CbcModel[numberModels];
97  OsiClpSolverInterface * allSolvers = new OsiClpSolverInterface[numberModels];
98  CbcSolverUsefulData * data = new CbcSolverUsefulData[numberModels];
99  threadStuff * allData = new threadStuff[numberModels];
100  // First populate first model
101  /* in a real application models would be different */
102  OsiClpSolverInterface & solver1 = allSolvers[0];
103  // Read in model using argv[1]
104  // and assert that it is a clean model
105  std::string mpsFileName;
106#if defined(SAMPLEDIR)
107  mpsFileName = SAMPLEDIR "/p0033.mps";
108#else
109  if (argc < 2) {
110    fprintf(stderr, "Do not know where to find sample MPS files.\n");
111    exit(1);
112  }
113#endif
114  if (argc>=2) mpsFileName = argv[1];
115  int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),"");
116  if( numMpsReadErrors != 0 )
117    {
118      printf("%d errors reading MPS file\n", numMpsReadErrors);
119      return numMpsReadErrors;
120    }
121  // Tell solver to return fast if presolve or initial solve infeasible
122  solver1.getModelPtr()->setMoreSpecialOptions(3);
123  // create models
124  for (int iModel=1;iModel<numberModels;iModel++) {
125    allSolvers[iModel]=solver1;
126  }
127  // now create CbcModels and copy parameters (up to end or -switch)
128  // Pass to Cbc initialize defaults
129  CbcModel modelA(solver1);
130  int lastArgPosition=2;
131  int lastArgc=0;
132  for (int iModel=0;iModel<numberModels;iModel++) {
133    allModels[iModel]=CbcModel(allSolvers[iModel]);
134    // default does NOT allow interrupts
135    // allow printing
136    data[iModel].noPrinting_ = false;
137    allData[iModel].model=allModels+iModel;
138    allData[iModel].data=data+iModel;
139    // See how many parameters
140    int endArgc=lastArgPosition;
141    int thisArgc=lastArgc;
142    for (;endArgc<argc;endArgc++) {
143      if (!strcmp(argv[endArgc],"-switch"))
144        break;
145    }
146    thisArgc=endArgc-lastArgPosition;
147    if (thisArgc>0)
148      lastArgc=thisArgc;
149    else
150      thisArgc=lastArgc;
151    // allow extra for -quit
152    char ** thisArgv=new char *[thisArgc+2];
153    thisArgv[0]=strdup(argv[0]);
154    int put=1;
155    for (int iArgc=lastArgPosition;iArgc<lastArgPosition+thisArgc;iArgc++) 
156      thisArgv[put++]=strdup(argv[iArgc]);
157    // add -quit
158    thisArgv[put++]=strdup("-quit");
159    allData[iModel].argc=put;
160    allData[iModel].argv=thisArgv;
161    if (endArgc<argc)
162      lastArgPosition=endArgc+1;
163  }
164#ifdef USE_PTHREAD
165  pthread_t * threadId = new pthread_t [numberModels];
166  // solve
167  for (int iModel=0;iModel<numberModels;iModel++) {
168    pthread_create(threadId+iModel, NULL, 
169                   doThread,
170                   allData+iModel);
171  }
172  // wait
173  for (int iModel=0;iModel<numberModels;iModel++) {
174    pthread_join(threadId[iModel], NULL);
175  }
176#else
177  for (int iModel=0;iModel<numberModels;iModel++) {
178    doThread(allData+iModel);
179  }
180#endif
181  // Just print first one
182  CbcModel * model = allModels;
183  // Solver was cloned so get current copy
184  OsiSolverInterface * solver = model->solver();
185  // Print solution if finished (could get from model->bestSolution() as well
186
187  if (model->bestSolution()) {
188   
189    const double * solution = solver->getColSolution();
190   
191    int iColumn;
192    int numberColumns = solver->getNumCols();
193    std::cout<<std::setiosflags(std::ios::fixed|std::ios::showpoint)<<std::setw(14);
194   
195    std::cout<<"--------------------------------------"<<std::endl;
196#ifdef USE_OSI_NAMES
197   
198    for (iColumn=0;iColumn<numberColumns;iColumn++) {
199      double value=solution[iColumn];
200      if (fabs(value)>1.0e-7&&solver->isInteger(iColumn)) 
201        std::cout<<std::setw(6)<<iColumn<<" "<<std::setw(8)<<setiosflags(std::ios::left)<<solver->getColName(iColumn)
202                 <<resetiosflags(std::ios::adjustfield)<<std::setw(14)<<" "<<value<<std::endl;
203    }
204#else
205    // names may not be in current solver - use original
206   
207    for (iColumn=0;iColumn<numberColumns;iColumn++) {
208      double value=solution[iColumn];
209      if (fabs(value)>1.0e-7&&solver->isInteger(iColumn)) 
210        std::cout<<std::setw(6)<<iColumn<<" "<<std::setw(8)<<setiosflags(std::ios::left)<<solver1.getModelPtr()->columnName(iColumn)
211                 <<resetiosflags(std::ios::adjustfield)<<std::setw(14)<<" "<<value<<std::endl;
212    }
213#endif
214    std::cout<<"--------------------------------------"<<std::endl;
215 
216    std::cout<<std::resetiosflags(std::ios::fixed|std::ios::showpoint|std::ios::scientific);
217  } else {
218    std::cout<<" No solution!"<<std::endl;
219  }
220  delete [] allModels;
221  delete [] allSolvers;
222  delete [] data;
223  for (int iModel=0;iModel<numberModels;iModel++) {
224    char ** argv = allData[iModel].argv;
225    int argc=allData[iModel].argc;
226    for (int i=0;i<argc;i++)
227      free(argv[i]);
228    delete [] argv;
229  }
230  delete [] allData;
231#ifdef USE_PTHREAD
232  delete [] threadId;
233#endif
234  return 0;
235}   
Note: See TracBrowser for help on using the repository browser.