LTP GCOV extension - code coverage report
Current view: directory - tpl/coin-cbc/cbc/Cgl/src/CglOddHole - CglOddHole.cpp
Test: Acro
Date: 2008-08-19 Instrumented lines: 457
Code covered: 3.9 % Executed lines: 18

       1                 : // Copyright (C) 2000, International Business Machines
       2                 : // Corporation and others.  All Rights Reserved.
       3                 : #if defined(_MSC_VER)
       4                 : // Turn off compiler warning about long names
       5                 : #  pragma warning(disable:4786)
       6                 : #endif
       7                 : #include <cstdlib>
       8                 : #include <cstdio>
       9                 : #include <cmath>
      10                 : #include <cfloat>
      11                 : #include <iostream>
      12                 : 
      13                 : #include "CoinHelperFunctions.hpp"
      14                 : #include "CoinPackedVector.hpp"
      15                 : #include "CoinPackedMatrix.hpp"
      16                 : #include "OsiRowCutDebugger.hpp"
      17                 : #include "CglOddHole.hpp"
      18                 : //#define CGL_DEBUG
      19                 : // We may want to sort cut
      20                 : typedef struct {double dj;double element; int sequence;} 
      21                 : double_double_int_triple;
      22                 : class double_double_int_triple_compare {
      23                 : public:
      24               0 :   bool operator() (double_double_int_triple x , double_double_int_triple y) const
      25                 :   {
      26               0 :     return ( x.dj < y.dj);
      27                 :   }
      28                 : }; 
      29                 : //-------------------------------------------------------------------------------
      30                 : // Generate three cycle cuts
      31                 : //------------------------------------------------------------------- 
      32                 : void CglOddHole::generateCuts(const OsiSolverInterface & si, OsiCuts & cs,
      33               0 :                               const CglTreeInfo info) const
      34                 : {
      35                 :   // Get basic problem information
      36               0 :   int nRows=si.getNumRows(); 
      37               0 :   int nCols=si.getNumCols(); 
      38                 :   
      39               0 :   const CoinPackedMatrix * rowCopy = si.getMatrixByRow();
      40                 : 
      41                 :   // Could do cliques and extra OSL cliques
      42                 :   // For moment just easy ones
      43                 :   
      44                 :   // If no information exists then get a list of suitable rows
      45                 :   // If it does then suitable rows are subset of information
      46                 :   
      47               0 :   CglOddHole temp;
      48               0 :   int * checkRow = new int[nRows];
      49                 :   int i;
      50               0 :   if (!suitableRows_) {
      51               0 :     for (i=0;i<nRows;i++) {
      52               0 :       checkRow[i]=1;
      53                 :     }
      54                 :   } else {
      55                 :     // initialize and extend rows to current size
      56               0 :     memset(checkRow,0,nRows*sizeof(int));
      57               0 :     memcpy(checkRow,suitableRows_,CoinMin(nRows,numberRows_)*sizeof(int));
      58                 :   }
      59               0 :   temp.createRowList(si,checkRow);
      60                 :   // now cut down further by only allowing rows with fractional solution
      61               0 :   double * solution = new double[nCols];
      62               0 :   memcpy(solution,si.getColSolution(),nCols*sizeof(double));
      63               0 :   const int * column = rowCopy->getIndices();
      64               0 :   const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
      65               0 :   const int * rowLength = rowCopy->getVectorLengths(); 
      66               0 :   const double * collower = si.getColLower();
      67               0 :   const double * colupper = si.getColUpper();
      68               0 :   int * suitable = temp.suitableRows_;
      69                 : 
      70                 :   // At present I am using new and delete as easier to see arrays in debugger
      71               0 :   int * fixed = new int[nCols]; // mark fixed columns 
      72                 : 
      73               0 :   for (i=0;i<nCols;i++) {
      74               0 :     if (si.isBinary(i) ) {
      75               0 :       fixed[i]=0;
      76               0 :       if (colupper[i]-collower[i]<epsilon_) {
      77               0 :         solution[i]=0.0;
      78               0 :         fixed[i]=2;
      79               0 :       } else if (solution[i]<epsilon_) {
      80               0 :         solution[i]=0.0;
      81               0 :         fixed[i]=-1;
      82               0 :       } else if (solution[i]>onetol_) {
      83               0 :         solution[i]=1.0;
      84               0 :         fixed[i]=+1;
      85                 :       }
      86                 :     } else {
      87                 :       //mark as fixed even if not (can not intersect any interesting rows)
      88               0 :       solution[i]=0.0;
      89               0 :       fixed[i]=3;
      90                 :     }
      91                 :   }
      92                 :   // first do packed
      93               0 :   const double * rowlower = si.getRowLower();
      94               0 :   const double * rowupper = si.getRowUpper();
      95               0 :   for (i=0;i<nRows;i++) {
      96               0 :     if (suitable[i]) {
      97                 :       int k;
      98               0 :       double sum=0.0;
      99               0 :       if (rowupper[i]>1.001) suitable[i]=-1;
     100               0 :       for (k=rowStart[i]; k<rowStart[i]+rowLength[i];k++) {
     101               0 :         int icol=column[k];
     102               0 :         if (!fixed[icol]) sum += solution[icol];
     103                 :       }
     104               0 :       if (sum<0.9) suitable[i]=-1; //say no good
     105                 :     }
     106                 :   }
     107                 : #ifdef CGL_DEBUG
     108                 :   const OsiRowCutDebugger * debugger = si.getRowCutDebugger();
     109                 :   if (debugger&&!debugger->onOptimalPath(si))
     110                 :     debugger = NULL;
     111                 : #else
     112               0 :   const OsiRowCutDebugger * debugger = NULL;
     113                 : #endif
     114                 :   temp.generateCuts(debugger, *rowCopy,solution,
     115               0 :                     si.getReducedCost(),cs,suitable,fixed,true);
     116                 :   // now cover
     117                 :   //if no >= then skip
     118               0 :   bool doCover=false;
     119               0 :   int nsuitable=0;
     120               0 :   for (i=0;i<nRows;i++) {
     121               0 :     suitable[i]=abs(suitable[i]);
     122               0 :     if (suitable[i]) {
     123                 :       int k;
     124               0 :       double sum=0.0;
     125               0 :       if (rowlower[i]<0.999) sum=2.0;
     126               0 :       if (rowupper[i]>1.001) doCover=true;
     127               0 :       for (k=rowStart[i]; k<rowStart[i]+rowLength[i];k++) {
     128               0 :         int icol=column[k];
     129               0 :         if (!fixed[icol]) sum += solution[icol];
     130               0 :         if (fixed[icol]==1) sum=2.0; //don't use if any at 1
     131                 :       }
     132               0 :       if (sum>1.1) {
     133               0 :         suitable[i]=-1; //say no good
     134                 :       } else {
     135               0 :         nsuitable++;
     136                 :       }
     137                 :     }
     138                 :   }
     139               0 :   if (doCover&&nsuitable) 
     140                 :     temp.generateCuts(debugger, *rowCopy,solution,si.getReducedCost(),
     141               0 :                       cs,suitable,fixed,false);
     142               0 :   delete [] checkRow;
     143               0 :   delete [] solution;
     144               0 :   delete [] fixed;
     145                 :     
     146               0 : }
     147                 : void CglOddHole::generateCuts(const OsiRowCutDebugger * debugger,
     148                 :                               const CoinPackedMatrix & rowCopy, 
     149                 :                                  const double * solution, 
     150                 :                               const double * dj, OsiCuts & cs,
     151                 :                                  const int * suitableRow,
     152                 :                               const int * fixedColumn,
     153               0 :                               bool packed)
     154                 : {
     155               0 :   CoinPackedMatrix columnCopy = rowCopy;
     156               0 :   columnCopy.reverseOrdering();
     157                 : 
     158                 :   // Get basic problem information
     159               0 :   int nRows=columnCopy.getNumRows(); 
     160               0 :   int nCols=columnCopy.getNumCols(); 
     161                 :   
     162               0 :   const int * column = rowCopy.getIndices();
     163               0 :   const CoinBigIndex * rowStart = rowCopy.getVectorStarts();
     164               0 :   const int * rowLength = rowCopy.getVectorLengths(); 
     165                 :   
     166               0 :   const int * row = columnCopy.getIndices();
     167               0 :   const CoinBigIndex * columnStart = columnCopy.getVectorStarts();
     168               0 :   const int * columnLength = columnCopy.getVectorLengths(); 
     169                 : 
     170                 :   // we need only look at suitable rows and variables with unsatisfied 0-1
     171                 :   // lookup from true row to compressed matrix
     172               0 :   int * mrow = new int[nRows];
     173                 :   // lookup from true column to compressed
     174               0 :   int * lookup = new int[nCols];
     175                 :   // number of columns in compressed matrix
     176               0 :   int nSmall=0;
     177                 :   int i;
     178                 :   //do lookup from true sequence to compressed
     179               0 :   int n=0;
     180               0 :   for (i=0;i<nRows;i++) {
     181               0 :     if (suitableRow[i]>0) {
     182               0 :       mrow[i]=n++;
     183                 :     } else {
     184               0 :       mrow[i]=-1;
     185                 :     }
     186                 :   }
     187               0 :   for (i=0;i<nCols;i++) {
     188               0 :     if (!fixedColumn[i]) {
     189               0 :       lookup[i]=nSmall++;
     190                 :     } else {
     191               0 :       lookup[i]=-1;
     192                 :     }
     193                 :   }
     194               0 :   int nSmall2=2*nSmall;
     195                 :   // we don't know how big matrix will be
     196                 : #define MAXELS 50000
     197               0 :   int maxels=MAXELS;
     198                 :   //How do I do reallocs in C++?
     199                 :   // 1.0 - value x(i) - value x(j) for each node pair (or reverse if cover) 
     200               0 :   double * cost = (double *) malloc(maxels*sizeof(double));
     201                 :   // arc i.e. j which can be reached from i
     202               0 :   int * to= (int *) malloc(maxels*sizeof(int));
     203                 :   //original row for each arc
     204               0 :   int * rowfound=(int *) malloc(maxels*sizeof(int));
     205                 :   // start of each column
     206               0 :   int * starts=new int[2*nSmall+1];
     207               0 :   starts[0]=0;
     208                 :   // useful array for marking if already connected
     209               0 :   int * mark =new int[nSmall2];
     210               0 :   memset(mark,0,nSmall2*sizeof(int));
     211               0 :   n=0; //number of elements in matrix
     212               0 :   for (i=0;i<nCols;i++) {
     213               0 :     int icol=lookup[i];
     214               0 :     if (icol>=0) {
     215                 :       // column in compressed matrix
     216                 :       int k;
     217               0 :       double dd=1.0000001-solution[i];
     218               0 :       mark[icol]=1;
     219                 :       // reallocate if matrix reached size limit
     220               0 :       if (n+nCols>maxels) {
     221               0 :         maxels*=2;
     222               0 :         cost=(double *) realloc(cost,maxels*sizeof(int));
     223               0 :         to=(int *) realloc(to,maxels*sizeof(int));
     224               0 :         rowfound=(int *) realloc(rowfound,maxels*sizeof(int));
     225                 :       }
     226                 :       // get all other connected variables
     227               0 :       for (k=columnStart[i];k<columnStart[i]+columnLength[i];k++) {
     228               0 :         int irow=row[k];
     229               0 :         int jrow=mrow[irow];
     230                 :         // but only if row in compressed matrix
     231               0 :         if (jrow>=0) {
     232                 :           int j;
     233               0 :           for (j=rowStart[irow];j<rowStart[irow]+rowLength[irow];j++) {
     234               0 :             int jcol=column[j];
     235               0 :             int kcol=lookup[jcol];
     236               0 :             if (kcol>=0&&!mark[kcol]) {
     237               0 :               cost[n]=dd-solution[jcol];
     238               0 :               to[n]=kcol;
     239               0 :               rowfound[n++]=irow;//original row
     240               0 :               mark[kcol]=1;
     241                 :             }
     242                 :           }
     243                 :         }
     244                 :       }
     245               0 :       starts[icol+1]=n;
     246                 :       // zero out markers for next column
     247               0 :       mark[icol]=0;
     248               0 :       for (k=starts[icol];k<starts[icol+1];k++) {
     249               0 :         int ito=to[k];
     250               0 :         if (ito<0||ito>=nSmall) abort();
     251               0 :         mark[to[k]]=0;
     252                 :       }
     253                 :     }
     254                 :   }
     255                 :   //if cover then change sign - otherwise make sure positive
     256               0 :   if (packed) {
     257               0 :     for (i=0;i<n;i++) {
     258               0 :       if (cost[i]<1.0e-10) {
     259               0 :         cost[i]=1.0e-10;
     260                 :       }
     261                 :     }
     262                 :   } else {
     263               0 :     for (i=0;i<n;i++) {
     264               0 :       cost[i]=-cost[i];
     265               0 :       if (cost[i]<1.0e-10) {
     266               0 :         cost[i]=1.0e-10;
     267                 :       }
     268                 :     }
     269                 :   }
     270                 :   // we are going to double size 
     271                 : 
     272               0 :   if (2*n>maxels) {
     273               0 :     maxels=2*n;
     274               0 :     cost=(double *) realloc(cost,maxels*sizeof(double));
     275               0 :     to=(int *) realloc(to,maxels*sizeof(int));
     276               0 :     rowfound=(int *) realloc(rowfound,maxels*sizeof(int));
     277                 :   }
     278                 :   /* copy and make bipartite*/
     279                 : 
     280               0 :   for (i=0;i<nSmall;i++) {
     281               0 :     int k,j=i+nSmall;
     282               0 :     for (k=starts[i];k<starts[i+1];k++) {
     283               0 :       int ito=to[k];
     284               0 :       to[n]=ito;
     285               0 :       to[k]=ito+nSmall;
     286               0 :       cost[n]=cost[k];
     287               0 :       rowfound[n++]=rowfound[k];;
     288                 :     }
     289               0 :     starts[j+1]=n;
     290                 :   }
     291                 :   //random numbers to winnow out duplicate cuts
     292               0 :   double * check = new double[nCols];
     293               0 :   CoinSeedRandom(13579);
     294               0 :   for (i=0;i<nCols;i++) {
     295               0 :     check[i]=CoinDrand48();
     296                 :   }
     297                 : 
     298                 :   // Shortest path algorithm from Dijkstra - is there a better one?
     299                 : 
     300                 :   typedef struct {
     301                 :     double cost; //cost to starting node
     302                 :     int back; //previous node
     303                 :   } Path;
     304                 :   typedef struct {
     305                 :     double cost; //cost to starting node
     306                 :     int node; //node
     307                 :   } Item;
     308               0 :   Item * stack = new Item [nSmall2];
     309               0 :   Path * path = new Path [nSmall2];
     310                 :   // arrays below are used only if looks promising
     311                 :   // allocate here
     312                 :   // we don't know how many cuts will be generated
     313               0 :   int ncuts=0;
     314               0 :   int maxcuts=1000;
     315               0 :   double * hash = (double *) malloc(maxcuts*sizeof(double));
     316                 :   // to clean (should not be needed)
     317               0 :   int * clean = new int[nSmall2];
     318               0 :   int * candidate = new int[CoinMax(nSmall2,nCols)];
     319               0 :   double * element = new double[nCols];
     320                 :   // in case we want to sort
     321                 :   double_double_int_triple * sortit = 
     322               0 :     new double_double_int_triple [nCols];
     323               0 :   memset(mark,0,nSmall2*sizeof(int));
     324               0 :   int * countcol = new int[nCols];
     325               0 :   memset(countcol,0,nCols*sizeof(int));
     326               0 :   int bias = packed ? 0 : 1; //amount to add before halving
     327                 :   // If nSmall large then should do a randomized subset
     328                 :   // Improvement 1
     329                 :   int icol;
     330               0 :   for (icol=0;icol<nSmall;icol++) {
     331                 :     int j;
     332               0 :     int jcol=icol+nSmall;
     333               0 :     int istack=1;
     334               0 :     for (j=0;j<nSmall2;j++) {
     335               0 :       path[j].cost=1.0e70;
     336               0 :       path[j].back=nSmall2+1;
     337                 :     }
     338               0 :     path[icol].cost=0.0;
     339               0 :     path[icol].back=-1;
     340               0 :     stack[0].cost=0.0;
     341               0 :     stack[0].node=icol;
     342               0 :     mark[icol]=1;
     343               0 :     while(istack) {
     344               0 :       Item thisItem=stack[--istack];
     345               0 :       double thisCost=thisItem.cost;
     346               0 :       int inode=thisItem.node;
     347                 :       int k;
     348               0 :       mark[inode]=0; //say available for further work
     349                 :       // See if sorting every so many would help (and which way)?
     350                 :       // Improvement 2
     351               0 :       for (k=starts[inode];k<starts[inode+1];k++) {
     352               0 :         int jnode=to[k];
     353               0 :         if (!mark[jnode]&&thisCost+cost[k]<path[jnode].cost-1.0e-12) {
     354               0 :           path[jnode].cost=thisCost+cost[k];
     355               0 :           path[jnode].back=inode;
     356                 :           // add to stack
     357               0 :           stack[istack].cost=path[jnode].cost;
     358               0 :           stack[istack++].node=jnode;
     359               0 :           mark[jnode]=1;
     360                 : #ifdef CGL_DEBUG
     361                 :           assert (istack<=nSmall2);
     362                 : #endif
     363                 :         }
     364                 :       }
     365                 :     }
     366               0 :     bool good=(path[jcol].cost<0.9999);
     367                 : 
     368               0 :     if (good)  { /* try */
     369                 :       int ii;
     370               0 :       int nrow2=0;
     371               0 :       int nclean=0;
     372               0 :       double sum=0;
     373                 : #ifdef CGL_DEBUG
     374                 :       printf("** %d ",jcol-nSmall);
     375                 : #endif
     376               0 :       ii=1;
     377               0 :       candidate[0]=jcol;
     378               0 :       while(jcol!=icol) {
     379                 :         int jjcol;
     380               0 :         jcol=path[jcol].back;
     381               0 :         if (jcol>=nSmall) {
     382               0 :           jjcol=jcol-nSmall;
     383                 :         } else {
     384               0 :           jjcol=jcol;
     385                 :         }
     386                 : #ifdef CGL_DEBUG
     387                 :         printf(" %d",jjcol);
     388                 : #endif
     389               0 :         if (mark[jjcol]) {
     390                 :           // good=false;
     391                 :           // probably means this is from another cycle (will have been found)
     392                 :           // one of cycles must be zero cost
     393                 :           // printf("variable already on chain!\n");
     394                 :         } else {
     395               0 :           mark[jjcol]=1;
     396               0 :           clean[nclean++]=jjcol;
     397               0 :           candidate[ii++]=jcol;
     398                 : #ifdef CGL_DEBUG
     399                 :           assert (ii<=nSmall2);
     400                 : #endif
     401                 :         }
     402                 :       }
     403                 : #ifdef CGL_DEBUG
     404                 :       printf("\n");
     405                 : #endif
     406               0 :       for (j=0;j<nclean;j++) {
     407               0 :         int k=clean[j];
     408               0 :         mark[k]=0;
     409                 :       }
     410               0 :       if (good) {
     411                 :         int k;
     412               0 :         for (k=ii-1;k>0;k--) {
     413               0 :           int jk,kk=candidate[k];
     414               0 :           int ix=0;
     415               0 :           for (jk=starts[kk];jk<starts[kk+1];jk++) {
     416               0 :             int ito=to[jk];
     417               0 :             if (ito==candidate[k-1]) {
     418               0 :               ix=1;
     419                 :               // back to original row
     420               0 :               mrow[nrow2++]=rowfound[jk];
     421               0 :               break;
     422                 :             }
     423                 :           }
     424               0 :           if (!ix) {
     425               0 :             good=false;
     426                 :           }
     427                 :         }
     428               0 :         if ((nrow2&1)!=1) {
     429               0 :           good=false;
     430                 :         }
     431               0 :         if (good) {
     432               0 :           int nincut=0;
     433               0 :           for (k=0;k<nrow2;k++) {
     434               0 :             int j,irow=mrow[k];
     435               0 :             for (j=rowStart[irow];j<rowStart[irow]+rowLength[irow];j++) {
     436               0 :               int icol=column[j];
     437               0 :               if (!countcol[icol]) candidate[nincut++]=icol;
     438               0 :               countcol[icol]++;
     439                 :             }
     440                 :           }
     441                 : #ifdef CGL_DEBUG
     442                 :           printf("true constraint %d",nrow2);
     443                 : #endif
     444               0 :           nrow2=nrow2>>1;
     445               0 :           double rhs=nrow2; 
     446               0 :           if (!packed) rhs++; // +1 for cover
     447               0 :           ii=0;
     448               0 :           for (k=0;k<nincut;k++) {
     449               0 :             int jcol=candidate[k];
     450               0 :             if (countcol[jcol]) {
     451                 : #ifdef CGL_DEBUG
     452                 :               printf(" %d %d",jcol,countcol[jcol]);
     453                 : #endif
     454               0 :               int ihalf=(countcol[jcol]+bias)>>1;
     455               0 :               if (ihalf) {
     456               0 :                 element[ii]=ihalf;
     457               0 :                 sum+=solution[jcol]*element[ii];
     458                 :                 /*printf("%d %g %g\n",jcol,element[ii],sumall[jcol]);*/
     459               0 :                 candidate[ii++]=jcol;
     460                 :               }
     461               0 :               countcol[jcol]=0;
     462                 :             }
     463                 :           }
     464                 : #ifdef CGL_DEBUG
     465                 :           printf("\n");
     466                 : #endif
     467               0 :           OsiRowCut rc;
     468               0 :           double violation=0.0;
     469               0 :           if (packed) {
     470               0 :             violation = sum-rhs;
     471               0 :             rc.setLb(-DBL_MAX);
     472               0 :             rc.setUb(rhs);   
     473                 :           } else {
     474                 :             // other way for cover
     475               0 :             violation = rhs-sum;
     476               0 :             rc.setUb(DBL_MAX);
     477               0 :             rc.setLb(rhs);   
     478                 :           }
     479               0 :           if (violation<minimumViolation_) {
     480                 : #ifdef CGL_DEBUG
     481                 :             printf("why no cut\n");
     482                 : #endif
     483               0 :             good=false;
     484                 :           } else {
     485               0 :             if (((double) ii) * minimumViolationPer_>violation||
     486                 :                 ii>maximumEntries_) {
     487                 : #ifdef CGL_DEBUG
     488                 :               printf("why no cut\n");
     489                 : #endif
     490               0 :               if (packed) {
     491                 :                 // sort and see if we can get down to length
     492                 :                 // relax by taking out ones with solution 0.0
     493               0 :                 nincut=ii;
     494               0 :                 for (k=0;k<nincut;k++) {
     495               0 :                   int jcol=candidate[k];
     496               0 :                   double value = fabs(dj[jcol]);
     497               0 :                   if (solution[jcol])
     498               0 :                   value = -solution[jcol];
     499               0 :                   sortit[k].dj=value;
     500               0 :                   sortit[k].element=element[k];
     501               0 :                   sortit[k].sequence=jcol;
     502                 :                 }
     503                 :                 // sort 
     504               0 :                 std::sort(sortit,sortit+nincut,double_double_int_triple_compare());
     505               0 :                 nincut = min(nincut,maximumEntries_);
     506               0 :                 sum=0.0;
     507               0 :                 for (k=0;k<nincut;k++) {
     508               0 :                   int jcol=sortit[k].sequence;
     509               0 :                   candidate[k]=jcol;
     510               0 :                   element[k]=sortit[k].element;
     511               0 :                   sum+=solution[jcol]*element[k];
     512                 :                 }
     513               0 :                 violation = sum-rhs;
     514               0 :                 ii=nincut;
     515               0 :                 if (violation<minimumViolation_) {
     516               0 :                   good=false;
     517                 :                 }
     518                 :               } else { 
     519               0 :                 good=false;
     520                 :               }
     521                 :             }
     522                 :           }
     523               0 :           if (good) {
     524                 :             //this assumes not many cuts
     525                 :             int j;
     526                 : #if 0
     527                 :             double value=0.0;
     528                 :             for (j=0;j<ii;j++) {
     529                 :               int icol=candidate[j];
     530                 :               value += check[icol]*element[j];
     531                 :             }
     532                 : #else
     533               0 :             CoinPackedVector candidatePv(ii,candidate,element);
     534               0 :             candidatePv.sortIncrIndex();
     535               0 :             double value = candidatePv.dotProduct(check);
     536                 : #endif
     537                 : 
     538               0 :             for (j=0;j<ncuts;j++) {
     539               0 :               if (value==hash[j]) {
     540                 :                 //could check equality - quicker just to assume
     541               0 :                 break;
     542                 :               }
     543                 :             }
     544               0 :             if (j==ncuts) {
     545                 :               //new
     546               0 :               if (ncuts==maxcuts) {
     547               0 :                 maxcuts *= 2;
     548               0 :                 hash = (double *) realloc(hash,maxcuts*sizeof(double));
     549                 :               }
     550               0 :               hash[ncuts++]=value;
     551               0 :               rc.setRow(ii,candidate,element);
     552                 : #ifdef CGL_DEBUG
     553                 :               printf("sum %g rhs %g %d\n",sum,rhs,ii);
     554                 :               if (debugger) 
     555                 :                 assert(!debugger->invalidCut(rc)); 
     556                 : #endif
     557               0 :               cs.insert(rc);
     558               0 :             }
     559               0 :           }
     560                 :         }
     561                 :         /* end of adding cut */
     562                 :       }
     563                 :     }
     564                 :   }
     565               0 :   delete [] countcol;
     566               0 :   delete [] element;
     567               0 :   delete [] candidate;
     568               0 :   delete [] sortit;
     569               0 :   delete [] clean;
     570               0 :   delete [] path;
     571               0 :   delete [] stack;
     572               0 :   free(hash);
     573               0 :   delete [] check;
     574               0 :   delete [] mark;
     575               0 :   delete [] starts;
     576               0 :   delete [] lookup;
     577               0 :   delete [] mrow;
     578               0 :   free(rowfound);
     579               0 :   free(to);
     580               0 :   free(cost);
     581               0 : }
     582                 : 
     583                 : // Create a list of rows which might yield cuts
     584                 : // The possible parameter is a list to cut down search
     585                 : void CglOddHole::createRowList( const OsiSolverInterface & si,
     586               0 :                       const int * possible)
     587                 : {
     588                 :   // Get basic problem information
     589               0 :   int nRows=si.getNumRows(); 
     590                 :   
     591               0 :   const CoinPackedMatrix * rowCopy = si.getMatrixByRow();
     592                 : 
     593               0 :   const int * column = rowCopy->getIndices();
     594               0 :   const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
     595               0 :   const int * rowLength = rowCopy->getVectorLengths(); 
     596                 :   
     597                 :   int rowIndex;
     598               0 :   delete [] suitableRows_;
     599               0 :   numberRows_=nRows;
     600                 : 
     601               0 :   const double * rowElements = rowCopy->getElements();
     602               0 :   const double * rowupper = si.getRowUpper();
     603               0 :   const double * rowlower = si.getRowLower();
     604               0 :   const double * collower = si.getColLower();
     605               0 :   const double * colupper = si.getColUpper();
     606                 : 
     607               0 :   suitableRows_=new int[nRows];
     608               0 :   if (possible) {
     609               0 :     memcpy(suitableRows_,possible,nRows*sizeof(int));
     610                 :   } else {
     611                 :     int i;
     612               0 :     for (i=0;i<nRows;i++) {
     613               0 :       suitableRows_[i]=1;
     614                 :     }
     615                 :   }
     616               0 :   for (rowIndex=0; rowIndex<nRows; rowIndex++){
     617               0 :     double rhs1=rowupper[rowIndex];
     618               0 :     double rhs2=rowlower[rowIndex];
     619               0 :     if (suitableRows_[rowIndex]) {
     620                 :       int i;
     621               0 :       bool goodRow=true;
     622               0 :       for (i=rowStart[rowIndex];
     623                 :            i<rowStart[rowIndex]+rowLength[rowIndex];i++) {
     624               0 :         int thisCol=column[i];
     625               0 :         if (colupper[thisCol]-collower[thisCol]>epsilon_) {
     626                 :           // could allow general integer variables but unlikely
     627               0 :           if (!si.isBinary(thisCol) ) {
     628               0 :             goodRow=false;
     629               0 :             break;
     630                 :           }
     631               0 :           if (fabs(rowElements[i]-1.0)>epsilon_) {
     632               0 :             goodRow=false;
     633               0 :             break;
     634                 :           }
     635                 :         } else {
     636               0 :           rhs1 -= collower[thisCol]*rowElements[i];
     637               0 :           rhs2 -= collower[thisCol]*rowElements[i];
     638                 :         }
     639                 :       }
     640               0 :       if (fabs(rhs1-1.0)>epsilon_&&fabs(rhs2-1.0)>epsilon_) {
     641               0 :         goodRow=false;
     642                 :       }
     643               0 :       if (goodRow) {
     644               0 :         suitableRows_[rowIndex]=1;
     645                 :       } else {
     646               0 :         suitableRows_[rowIndex]=0;
     647                 :       }
     648                 :     }
     649                 :   }
     650               0 : }
     651                 :   /// This version passes in a list - 1 marks possible
     652               0 : void CglOddHole::createRowList(int numberRows, const int * whichRow)
     653                 : {
     654               0 :   suitableRows_=new int [numberRows];
     655               0 :   numberRows_=numberRows;
     656               0 :   memcpy(suitableRows_,whichRow,numberRows*sizeof(int));
     657               0 : }
     658                 : 
     659                 : // Create a list of extra row cliques which may not be in matrix
     660                 : // At present these are classical cliques
     661                 : void CglOddHole::createCliqueList(int numberCliques, const int * cliqueStart,
     662               0 :                      const int * cliqueMember)
     663                 : {
     664               0 :   numberCliques_=numberCliques;
     665               0 :   startClique_=new int[numberCliques_+1];
     666               0 :   memcpy(startClique_,cliqueStart,(numberCliques_+1)*sizeof(int));
     667               0 :   int length=startClique_[numberCliques_];
     668               0 :   member_=new int[length];
     669               0 :   memcpy(member_,cliqueMember,length*sizeof(int));
     670               0 : }
     671                 : // Returns how many rows might give three cycle cuts
     672               0 : int CglOddHole::numberPossible()
     673                 : {
     674               0 :   int i,n=0;
     675               0 :   for (i=0;i<numberRows_;i++) {
     676               0 :     if (suitableRows_[i]) n++;
     677                 :   }
     678               0 :   return n;
     679                 : }
     680                 : 
     681                 : 
     682                 : //-------------------------------------------------------------------
     683                 : // Default Constructor 
     684                 : //-------------------------------------------------------------------
     685              10 : CglOddHole::CglOddHole ()
     686                 : :
     687                 : CglCutGenerator(),
     688                 : epsilon_(1.0e-08),
     689              10 : onetol_(1-epsilon_)
     690                 : {
     691                 :   // null copy of suitable rows
     692              10 :   numberRows_=0;
     693              10 :   suitableRows_=NULL;
     694              10 :   startClique_=NULL;
     695              10 :   numberCliques_=0;
     696              10 :   member_=NULL;
     697              10 :   minimumViolation_=0.001;
     698              10 :   minimumViolationPer_=0.0003;
     699              10 :   maximumEntries_=100;
     700              10 : }
     701                 : 
     702                 : //-------------------------------------------------------------------
     703                 : // Copy constructor 
     704                 : //-------------------------------------------------------------------
     705                 : CglOddHole::CglOddHole (
     706               0 :                                                               const CglOddHole & source)
     707                 :                                                               :
     708                 : CglCutGenerator(source),
     709                 : epsilon_(source.epsilon_),
     710               0 : onetol_(source.onetol_)
     711                 : {  
     712                 :   // copy list of suitable rows
     713               0 :   numberRows_=source.numberRows_;
     714               0 :   if (numberRows_) {
     715               0 :     suitableRows_=new int[numberRows_];
     716               0 :     memcpy(suitableRows_,source.suitableRows_,numberRows_*sizeof(int));
     717                 :   } else {
     718               0 :     suitableRows_=NULL;
     719                 :   }
     720                 :   // copy list of cliques
     721               0 :   numberCliques_=source.numberCliques_;
     722               0 :   if (numberCliques_) {
     723               0 :     startClique_=new int[numberCliques_+1];
     724               0 :     memcpy(startClique_,source.startClique_,(numberCliques_+1)*sizeof(int));
     725               0 :     int length=startClique_[numberCliques_];
     726               0 :     member_=new int[length];
     727               0 :     memcpy(member_,source.member_,length*sizeof(int));
     728                 :   } else {
     729               0 :     startClique_=NULL;
     730               0 :     member_=NULL;
     731                 :   }
     732               0 :   minimumViolation_=source.minimumViolation_;
     733               0 :   minimumViolationPer_=source.minimumViolationPer_;
     734               0 :   maximumEntries_=source.maximumEntries_;
     735               0 : }
     736                 : 
     737                 : //-------------------------------------------------------------------
     738                 : // Clone
     739                 : //-------------------------------------------------------------------
     740                 : CglCutGenerator *
     741               0 : CglOddHole::clone() const
     742                 : {
     743               0 :   return new CglOddHole(*this);
     744                 : }
     745                 : 
     746                 : //-------------------------------------------------------------------
     747                 : // Destructor 
     748                 : //-------------------------------------------------------------------
     749              10 : CglOddHole::~CglOddHole ()
     750                 : {
     751                 :   // free memory
     752              10 :   delete [] suitableRows_;
     753              10 :   delete [] startClique_;
     754              10 :   delete [] member_;
     755              10 : }
     756                 : 
     757                 : //----------------------------------------------------------------
     758                 : // Assignment operator 
     759                 : //-------------------------------------------------------------------
     760                 : CglOddHole &
     761                 : CglOddHole::operator=(
     762               0 :                                          const CglOddHole& rhs)
     763                 : {
     764               0 :   if (this != &rhs) {
     765               0 :     CglCutGenerator::operator=(rhs);
     766               0 :     epsilon_=rhs.epsilon_;
     767               0 :     onetol_=rhs.onetol_;
     768               0 :     delete [] suitableRows_;
     769                 :     // copy list of suitable rows
     770               0 :     numberRows_=rhs.numberRows_;
     771               0 :     suitableRows_=new int[numberRows_];
     772               0 :     memcpy(suitableRows_,rhs.suitableRows_,numberRows_*sizeof(int));
     773               0 :     delete [] startClique_;
     774               0 :     delete [] member_;
     775                 :     // copy list of cliques
     776               0 :     numberCliques_=rhs.numberCliques_;
     777               0 :     if (numberCliques_) {
     778               0 :       startClique_=new int[numberCliques_+1];
     779               0 :       memcpy(startClique_,rhs.startClique_,(numberCliques_+1)*sizeof(int));
     780               0 :       int length=startClique_[numberCliques_];
     781               0 :       member_=new int[length];
     782               0 :       memcpy(member_,rhs.member_,length*sizeof(int));
     783                 :     } else {
     784               0 :       startClique_=NULL;
     785               0 :       member_=NULL;
     786                 :     }
     787               0 :     minimumViolation_=rhs.minimumViolation_;
     788               0 :     minimumViolationPer_=rhs.minimumViolationPer_;
     789               0 :     maximumEntries_=rhs.maximumEntries_;
     790                 :   }
     791               0 :   return *this;
     792                 : }
     793                 : // Minimum violation
     794                 : double 
     795               0 : CglOddHole::getMinimumViolation() const
     796                 : {
     797               0 :   return minimumViolation_;
     798                 : }
     799                 : void 
     800               0 : CglOddHole::setMinimumViolation(double value)
     801                 : {
     802               0 :   if (value>1.0e-8&&value<=0.5)
     803               0 :     minimumViolation_=value;
     804               0 : }
     805                 : // Minimum violation per entry
     806                 : double 
     807               0 : CglOddHole::getMinimumViolationPer() const
     808                 : {
     809               0 :   return minimumViolationPer_;
     810                 : }
     811                 : void 
     812               0 : CglOddHole::setMinimumViolationPer(double value)
     813                 : {
     814               0 :   if (value>1.0e-8&&value<=0.25)
     815               0 :     minimumViolationPer_=value;
     816               0 : }
     817                 : // Maximum number of entries in a cut
     818                 : int 
     819               0 : CglOddHole::getMaximumEntries() const
     820                 : {
     821               0 :   return maximumEntries_;
     822                 : }
     823                 : void 
     824               0 : CglOddHole::setMaximumEntries(int value)
     825                 : {
     826               0 :   if (value>2)
     827               0 :     maximumEntries_=value;
     828               0 : }
     829                 : 
     830                 : // This can be used to refresh any inforamtion
     831                 : void 
     832               0 : CglOddHole::refreshSolver(OsiSolverInterface * solver)
     833                 : {
     834              84 : }

Generated by: LTP GCOV extension version 1.4