source: trunk/Cbc/examples/cbc_driverC_sos.c @ 1565

Last change on this file since 1565 was 1549, checked in by lou, 9 years ago

Make Visual Studio v9 build work again.

File size: 15.2 KB
Line 
1/* Copyright (C) 2004-2007 EPRI
2Corporation and others.  All Rights Reserved. */
3
4/* This example shows the use of the "C" interface for CBC. */
5
6#include "Cbc_C_Interface.h"
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <assert.h>
11
12/* prototypes */
13void printSolution(Cbc_Model *cbc_model);
14Cbc_Model * getDefaultModel(int argc, const char *argv[]);
15
16
17/* Call back function - just says whenever it gets Clp0005 or Coin0002 */
18/* TODO: It seems that Cbc gives callbacks but not Coin */
19static void callBack(Cbc_Model * model, int messageNumber,
20                     int nDouble, const double * vDouble,
21                     int nInt, const int * vInt,
22                     int nString, char ** vString) 
23{
24  const char prefix[] = "cbc_driverC_sos.cpp::callBack(): ";
25  const int  VERBOSE = 4;
26  if (VERBOSE>0) printf("%s begin\n",prefix);
27  if (VERBOSE>1) printf("%s messageNumber %i\n",prefix,messageNumber);
28
29  if (messageNumber==1000002) {
30    /* Coin0002 */
31    assert (nString==1&&nInt==3);
32    printf("Name of problem is %s\n",vString[0]);
33    printf("row %d col %d el %d\n",vInt[0],vInt[1],vInt[2]);
34  } else if (messageNumber==5) {
35    /* Clp0005 */
36    int i;
37    assert (nInt==4&&nDouble==3); /* they may not all print */
38    for (i=0;i<3;i++)
39      printf("%d %g\n",vInt[i],vDouble[i]);
40  }
41
42  if (VERBOSE>0) printf("%s return\n",prefix);
43}
44
45/**
46* Get default model
47*/
48Cbc_Model * getDefaultModel(int argc, const char *argv[])
49{
50  const char prefix[] = "cbc_driverC_sos.cpp::getDefaultModel(): ";
51  const int  VERBOSE = 4;
52  Cbc_Model  *model;
53  int status; 
54
55  if (VERBOSE>0) printf("%s begin\n",prefix);
56  model = Cbc_newModel(); 
57
58  /** Amount of print out:
59  0 - none
60  1 - just final
61  2 - just factorizations
62  3 - as 2 plus a bit more
63  4 - verbose
64  above that 8,16,32 etc just for selective debug
65  */
66  Cbc_setLogLevel(model, 1);
67  if (VERBOSE>0) printf("%s Log Level %i\n", prefix, Cbc_logLevel(model));
68  /* register callback */
69  Cbc_registerCallBack(model,callBack);
70  /* Keep names when reading an mps file */
71  if (argc < 2) {
72#if defined(SAMPLEDIR)
73  /*
74    SAMPLEDIR should be something like "path/to/mps/directory/", including the
75    quotes and final directory separator. Don't forget to properly escape
76    '\' when using native Windows path syntax.
77  */
78    status=Cbc_readMps(model,SAMPLEDIR "p0033.mps") ;
79#else
80    fprintf(stderr, "Please specify the full path to an MPS file on the command line\n");
81    exit(1);
82#endif
83  }
84  else
85    status=Cbc_readMps(model,argv[1]);
86
87  if (status) {
88    fprintf(stderr,"Bad readMps %s\n",argv[1]);
89    fprintf(stdout,"Bad readMps %s\n",argv[1]);
90    exit(1);
91  }
92  Cbc_setOptimizationDirection(model, 1);
93  if (1) Cbc_setIntegerTolerance(model,  1.0e-5);
94
95  /* Solve initial LP relaxation */
96  Cbc_initialSolve(model);
97
98  if (VERBOSE>0) printf("%s return\n",prefix);
99  return model;
100} /* getDefaultModel() */
101
102void printSolution(Cbc_Model *cbc_model) {
103 
104  /*  Now to print out solution.  The methods used return modifiable
105      arrays while the alternative names return const pointers -
106      which is of course much more virtuous.
107     
108      This version just does non-zero column and row values.
109  */
110
111  /* If we have not kept names (parameter to readMps) this will be 0
112      assert(Cbc_lengthNames(cbc_model));
113  */
114  {
115    int  name_length = 256;
116    char model_name[256];
117    Cbc_problemName(cbc_model, name_length, model_name);
118    printf("Model Name = '%s'\n", model_name);
119  }
120  printf("Iteration Count = %i\n",Cbc_getIterationCount(cbc_model));
121  printf("Iteration Limit = %i\n",Cbc_maximumIterations(cbc_model));
122  printf("Is Abandoned = %i\n",Cbc_isAbandoned(cbc_model));
123  printf("Is Proven Optimal = %i\n",Cbc_isProvenOptimal(cbc_model));
124  printf("Is Proven Infeasible = %i\n",Cbc_isProvenPrimalInfeasible(cbc_model));
125  printf("Is Proven Dual Infeasible = %i\n",Cbc_isProvenDualInfeasible(cbc_model));
126  printf("Is Proven Unbounded = %i\n",(Cbc_infeasibilityRay(cbc_model) == NULL) ? 0 : 1);
127  printf("Is Primal Objective Limit Reached = %i\n",Cbc_isPrimalObjectiveLimitReached(cbc_model));
128  printf("Is Dual Objective Limit Reached = %i\n",Cbc_isDualObjectiveLimitReached(cbc_model));
129  printf("Is Iteration Limit Reached = %i\n",Cbc_isIterationLimitReached(cbc_model));
130  printf("Objective Sense = %g\n",Cbc_getObjSense(cbc_model));  /* (1 - minimize, -1 - maximize, 0 - ignore) */
131  printf("Primal Feasible = %i\n",Cbc_primalFeasible(cbc_model));
132  printf("Dual Feasible = %i\n",Cbc_dualFeasible(cbc_model));
133  printf("Dual Bound = %g\n",Cbc_dualBound(cbc_model));
134  printf("Infeasibility Cost = %g\n",Cbc_infeasibilityCost(cbc_model));
135  printf("Sum Dual Infeasibilities = %g\n",Cbc_sumDualInfeasibilities(cbc_model));
136  printf("Number Dual Infeasibilities = %i\n",Cbc_numberDualInfeasibilities(cbc_model));
137  printf("Sum Primal Infeasibilities = %g\n",Cbc_sumPrimalInfeasibilities(cbc_model));
138  printf("Number Primal Infeasibilities = %i\n",Cbc_numberPrimalInfeasibilities(cbc_model));
139  printf("Objective Value = %g\n",Cbc_objectiveValue(cbc_model)); 
140  printf("Optimization Direction = %g\n", Cbc_optimizationDirection(cbc_model));
141  printf("  (1 - minimize, -1 - maximize, 0 - ignore)\n");
142  printf("--------------------------------------\n");
143
144  /*  Rows */
145  {
146    int numberRows = Cbc_numberRows(cbc_model);
147    int iRow;
148
149    const double * rowPrimal = Cbc_getRowActivity(cbc_model);
150    const double * rowDual   = Cbc_getRowPrice(cbc_model);
151    const double * rowLower  = Cbc_getRowLower(cbc_model);
152    const double * rowUpper  = Cbc_getRowUpper(cbc_model);
153
154    assert(rowPrimal != NULL);
155    assert(rowDual   != NULL);
156    assert(rowLower  != NULL);
157    assert(rowUpper  != NULL);
158
159    printf("                       Primal          Dual         Lower         Upper\n");
160    for (iRow=0;iRow<numberRows;iRow++) {
161      double value;
162      value = rowDual[iRow];
163      if (value>1.0e-8||value<-1.0e-8) {
164        char name[20];
165        sprintf(name," Row%-4i",iRow);
166        printf("%6d %8s",iRow,name);
167        printf(" %13g",rowPrimal[iRow]);
168        printf(" %13g",rowDual[iRow]);
169        printf(" %13g",rowLower[iRow]);
170        printf(" %13g",rowUpper[iRow]);
171        printf("\n");
172      }
173    }
174  }
175  printf("--------------------------------------\n");
176  /* Columns */
177  {
178    int numberColumns = Cbc_numberColumns(cbc_model);
179    int iColumn;
180
181    const double * columnPrimal    = Cbc_getColSolution(cbc_model);
182    const double * columnDual      = Cbc_getReducedCost(cbc_model);
183    const double * columnLower     = Cbc_getColLower(cbc_model);
184    const double * columnUpper     = Cbc_getColUpper(cbc_model);
185    const double * columnObjective = Cbc_getObjCoefficients(cbc_model);
186
187    assert(columnPrimal    != NULL);
188    assert(columnDual      != NULL);
189    assert(columnLower     != NULL);
190    assert(columnUpper     != NULL);
191    assert(columnObjective != NULL);
192
193    printf("                       Primal          Dual         Lower         Upper          Cost\n");
194    for (iColumn=0;iColumn<numberColumns;iColumn++) {
195      double value;
196      value = columnPrimal[iColumn];
197      if (value>1.0e-8||value<-1.0e-8) {
198        char name[20];
199        sprintf(name," Col%-4i",iColumn);
200        /*      Cbc_columnName(cbc_model,iColumn,name); */
201        printf("%6d %8s",iColumn,name);
202        printf(" %13g",columnPrimal[iColumn]);
203        printf(" %13g",columnDual[iColumn]);
204        printf(" %13g",columnLower[iColumn]);
205        printf(" %13g",columnUpper[iColumn]);
206        printf(" %13g",columnObjective[iColumn]);
207        printf("\n");
208      }
209    }
210  }
211  printf("--------------------------------------\n");
212} /*  printSolution() */
213
214int main (int argc, const char *argv[])
215{
216  const char prefix[] = "cbc_driverC_sos.cpp:main(): ";
217  const int  VERBOSE = 4;
218  Cbc_Model * model, * model2;
219  double time1;
220  char modelName[80];
221  int numberIntegers;
222  int * integerVariable;
223
224  if (VERBOSE>0) printf("%s begin\n",prefix);
225  if (VERBOSE>0) printf("%s Version %g\n",prefix,Cbc_getVersion());
226
227  /* set model using the local routine for reading an MPS file */
228  model = getDefaultModel(argc, argv);
229  model2 = NULL;  /* used to keep model around */
230
231  /* This clause ought to set the initial basis, but does not yet work. */
232  {
233    int i;
234    int row_length = Cbc_getNumRows(model);
235    int col_length = Cbc_getNumCols(model);
236    int rim_length = row_length + col_length;
237    int elem_length = Cbc_getNumElements(model);
238
239    int * cbc_rowStatus    = NULL;
240    int * cbc_columnStatus = NULL;
241
242    if (0) {
243      fprintf(stdout,"%s row_length = %i\n", prefix, row_length);
244      fprintf(stdout,"%s col_length = %i\n", prefix, col_length);
245      fprintf(stdout,"%s rim_length = %i\n", prefix, rim_length);
246      fprintf(stdout,"%s elem_length = %i\n", prefix, elem_length);
247      fflush(stdout);
248    }
249    /* print solution status variables */
250    if (0) {
251      if (cbc_rowStatus) {
252        for (i = 0; i < row_length; i++) {
253          printf("%s cbc_rowStatus[%i] = %i\n", prefix, i, cbc_rowStatus[i]);
254          fflush(stdout);
255        }
256      } else {
257        fprintf(stdout,"%s cbc_rowStatus = %p\n", prefix, (void*)cbc_rowStatus);
258        fflush(stdout);
259      }
260      if (cbc_columnStatus) {
261        for (i = 0; i < row_length; i++) {
262          fprintf(stdout,"%s cbc_rowStatus[%i] = %i\n", prefix, i, cbc_columnStatus[i]);
263          fflush(stdout);
264        }
265      } else {
266        fprintf(stdout,"%s cbc_columnStatus = %p\n", prefix, (void*)cbc_columnStatus);
267        fflush(stdout);
268      }
269    }
270  }
271
272  /* Save model as a clone (does not work as of 2004). */
273  model2 = Cbc_clone(model);
274
275  /* Store which variables are integer as defined in the MPS file.
276     They will be set to Continuous before adding the SOS constraints. */
277
278  {
279    int i;
280    int numberColumns=Cbc_getNumCols(model);
281    numberIntegers = 0;
282    integerVariable = malloc(numberColumns*sizeof(int[1]));
283    for ( i=0;i<numberColumns;i++) {
284      if (Cbc_isInteger(model,i)) {
285        integerVariable[numberIntegers++]=i;
286        if (VERBOSE>3) printf("%s integerVariable[%i] = %i\n",prefix,
287          numberIntegers-1, integerVariable[numberIntegers-1]);
288      }
289    }
290  }
291  Cbc_problemName(model,80,modelName);
292
293  /* Solve the MPS version of the problem */
294  if (1) { 
295    if (VERBOSE>1) {
296      printf("%s Solve MPS version of the problem\n",prefix);
297      printf("%s Optimization Direction = %g (1 - minimize, -1 - maximize, 0 - ignore)\n",
298        prefix, Cbc_optimizationDirection(model)); 
299    }
300    /*    Cbc_setLogLevel(model, VERBOSE); // 4 is verbose */
301    time1 = Cbc_cpuTime(model) ;
302    Cbc_branchAndBound(model);
303    if (VERBOSE>1) printf("Model %s has %d rows and %d columns\n",
304      modelName,Cbc_numberRows(model),Cbc_numberColumns(model));
305
306    if (VERBOSE>1) printf("%s Solving model %s took %g seconds, %i nodes with objective %g\n",
307      prefix, modelName, (Cbc_cpuTime(model)-time1), 
308      Cbc_getNodeCount(model), Cbc_getObjValue(model));
309    if (VERBOSE>0) (!Cbc_status(model)) ? printf(" Finished\n") : printf(" Not finished\n");
310    if (VERBOSE>2) printSolution(model);
311  }
312  {
313   
314    /* SOS specification data
315       specify numberSets, numPoints, and whichRanges explicitly
316       NOTE: These need to be commented according to the MPS file.
317         Example_1_1: Cbc0004I MPS reads 1081 only columns out of 1085
318                      Then the 4th range goes out of bounds
319         Example_2: Cbc0006I The LP relaxation is infeasible or too expensive
320         Mod_RT_1: Cbc0006I The LP relaxation is infeasible or too expensive
321    */
322    const int numberSets = 
323      1; /* dummy
324    //    4; // Example_1_1
325    //    2;  // Example_2
326    //    2;  // Mod_RT_1
327    //    2;  // SITH */
328    const int numPoints = 
329      1; /* dummy
330    //    257; // Example_1_1
331    //    256;  // Example_2
332    //    257;  // Mod_RT_1
333    //    257;  // SITH */
334
335    const int whichRanges[1][2] = { /* counting from zero? */
336      {0,0} /* dummy */
337      /*   {56,312}, {313, 569}, {572, 828}, {829, 1085} // Example_1_1
338           {48, 303}, {304, 559} // Example_2
339           {45, 301}, {302, 558} // Mod_RT_1
340           {45, 301}, {302, 558} // SITH
341      */
342    };
343    /* the rest is determined parametrically */
344    int *len = malloc(numberSets* sizeof(int[1]));
345    int **which = malloc(numberSets* sizeof(int[1]));
346    int setNum, pointNum;
347    double *weights;
348    int i, j;
349    for (setNum = 0; setNum < numberSets; setNum++) {
350      len[setNum] = whichRanges[setNum][1] - whichRanges[setNum][0] + 1;
351      if (len[setNum] != numPoints) {
352        printf("%s ERROR: len[%i] (%i) != numPoints (%i)\n",
353          prefix, setNum, len[setNum], numPoints);
354        return 1;
355      }
356      which[setNum] = malloc(numPoints*sizeof(int[1]));
357      for (j = 0; j < len[setNum]; j++)
358        which[setNum][j] = whichRanges[setNum][0] + j; /* Example_2 */
359    }
360    weights = malloc(numPoints*sizeof(double[1])); 
361    for (pointNum = 0; pointNum < numPoints; pointNum++) weights[pointNum] = pointNum+1;
362
363    /* Now use SOS2
364       NOTE: Only enable this if known good SOS Specification (above)
365    */
366    if (1) { 
367      if (VERBOSE>1) printf("%s Use SOS2\n",prefix);
368
369      /* Restore model */
370      Cbc_deleteModel(model);
371      if (0) {
372        model = Cbc_clone(model2);
373      } else {
374        model = getDefaultModel(argc, argv); 
375      }
376      /*    Cbc_setLogLevel(model, 4); // 4 is verbose */
377      if (VERBOSE>1) printf("%s Model %s has %d rows and %d columns\n",
378        prefix, modelName,Cbc_numberRows(model),Cbc_numberColumns(model));
379
380      /* make SOS cuts */
381      for (i=0;i<numberIntegers;i++) {
382        int iColumn = integerVariable[i];
383        /* Stop being integer */
384        Cbc_setContinuous(model, iColumn);
385      }
386      /* add cut (0 - use dense, 1 - use sparse (TODO: test this)) */
387      if (0) for (i=0;i<numberSets;i++) {
388        printf(
389          "%s calling Cbc_addSOS(), len[%i] = %i, which[%i][0] = %i, which[%i][%i] = %i,\n  weights[0] = %g, weights[%i] = %g\n",
390          prefix, i, len[i], i, which[i][0], i, len[i]-1, which[i][len[i]-1], weights[0], len[i]-1, weights[len[i]-1]);
391        /*      Cbc_addSOS_Sparse(model,len[i],which[i],weights,i,2); */
392      } else {
393        int numObjects = numberSets; /* cannot pass const int */
394        Cbc_addSOS_Dense(model, numObjects, len, (const int**)which, (const double*)weights, 2);
395      }
396    }
397
398    Cbc_setOptimizationDirection(model, 1); /* 1 minimize */
399    if (VERBOSE>1) {
400      printf("%s Solve MPS version of the problem\n",prefix);
401      printf("%s Optimization Direction = %g (1 - minimize, -1 - maximize, 0 - ignore)\n",
402        prefix, Cbc_optimizationDirection(model)); 
403    }
404    if (VERBOSE>1) printf("%s calling Cbc_scaling()\n",prefix);
405    Cbc_scaling(model,1);
406    time1 = Cbc_cpuTime(model) ;
407    if (VERBOSE>1) printf("%s calling Cbc_initialSolve()\n",prefix);
408    Cbc_initialSolve(model);
409    if (VERBOSE>3) Cbc_printModel(model,prefix);
410    if (VERBOSE>1) printf("%s calling Cbc_branchAndBound()\n",prefix);
411    Cbc_branchAndBound(model);
412    if (VERBOSE>1) printf("%s %s took %g seconds, %i nodes with objective %g\n",
413      prefix, modelName, (Cbc_cpuTime(model)-time1), 
414      Cbc_getNodeCount(model), Cbc_getObjValue(model));
415    if (VERBOSE>0) (!Cbc_status(model)) ? printf(" Finished\n") : printf(" Not finished\n");
416    if (VERBOSE>2) printSolution(model);
417  }
418
419  if (VERBOSE>1) printf("%s Log Level %i\n", prefix, Cbc_logLevel(model));
420  if (VERBOSE>0) printf("%s return 0\n",prefix);
421  return 0;
422} /*  main() */
Note: See TracBrowser for help on using the repository browser.