Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

ClpSimplexPrimalQuadratic.cpp

00001 // Copyright (C) 2003, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 
00004 #include "CoinPragma.hpp"
00005 
00006 #include <math.h>
00007 
00008 #include "CoinHelperFunctions.hpp"
00009 #include "ClpSimplexPrimalQuadratic.hpp"
00010 #include "ClpPrimalQuadraticDantzig.hpp"
00011 #include "ClpPrimalColumnDantzig.hpp"
00012 #include "ClpQuadraticObjective.hpp"
00013 #include "ClpFactorization.hpp"
00014 #include "ClpNonLinearCost.hpp"
00015 #include "ClpPackedMatrix.hpp"
00016 #include "CoinIndexedVector.hpp"
00017 #include "CoinWarmStartBasis.hpp"
00018 #include "CoinMpsIO.hpp"
00019 #include "ClpPrimalColumnPivot.hpp"
00020 #include "ClpMessage.hpp"
00021 #include <cfloat>
00022 #include <cassert>
00023 #include <string>
00024 #include <stdio.h>
00025 #include <iostream>
00026 class tempMessage :
00027    public CoinMessageHandler {
00028 
00029 public:
00030   virtual int print() ;
00031   tempMessage(ClpSimplex * model);
00032   ClpSimplex * model_;
00033 };
00034 
00035 // Constructor with pointer to model
00036 tempMessage::tempMessage(ClpSimplex * model)
00037   : CoinMessageHandler(),
00038     model_(model)
00039 {
00040 }
00041 int
00042 tempMessage::print()
00043 {
00044   static int numberFeasible=0;
00045   if (currentSource()=="Clp") {
00046     if (currentMessage().externalNumber()==5) { 
00047       if (!numberFeasible&&!model_->nonLinearCost()->numberInfeasibilities()) {
00048         numberFeasible++;
00049         model_->setMaximumIterations(0);
00050       }
00051     }  
00052   }
00053   return CoinMessageHandler::print();
00054 }
00055 
00056 // A sequential LP method
00057 int 
00058 ClpSimplexPrimalQuadratic::primalSLP(int numberPasses, double deltaTolerance)
00059 {
00060   // Are we minimizing or maximizing
00061   double whichWay=optimizationDirection();
00062   if (whichWay<0.0)
00063     whichWay=-1.0;
00064   else if (whichWay>0.0)
00065     whichWay=1.0;
00066 
00067   // This is as a user would see
00068 
00069   int numberColumns = this->numberColumns();
00070   int numberRows = this->numberRows();
00071   double * columnLower = this->columnLower();
00072   double * columnUpper = this->columnUpper();
00073   double * objective = this->objective();
00074   double * solution = this->primalColumnSolution();
00075   
00076   // Save objective
00077   
00078   double * saveObjective = new double [numberColumns];
00079   memcpy(saveObjective,objective,numberColumns*sizeof(double));
00080 
00081   // Get list of non linear columns
00082   ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
00083   CoinPackedMatrix * quadratic = NULL;
00084   if (quadraticObj)
00085     quadratic = quadraticObj->quadraticObjective();
00086   if (!quadratic) {
00087     // no quadratic part
00088     return primal(0);
00089   }
00090   int numberNonLinearColumns = 0;
00091   int iColumn;
00092   int * listNonLinearColumn = new int[numberColumns];
00093   memset(listNonLinearColumn,0,numberColumns*sizeof(int));
00094   const int * columnQuadratic = quadratic->getIndices();
00095   const int * columnQuadraticStart = quadratic->getVectorStarts();
00096   const int * columnQuadraticLength = quadratic->getVectorLengths();
00097   const double * quadraticElement = quadratic->getElements();
00098   for (iColumn=0;iColumn<numberColumns;iColumn++) {
00099     int j;
00100     for (j=columnQuadraticStart[iColumn];
00101          j<columnQuadraticStart[iColumn]+columnQuadraticLength[iColumn];j++) {
00102       int jColumn = columnQuadratic[j];
00103       listNonLinearColumn[jColumn]=1;
00104       listNonLinearColumn[iColumn]=1;
00105     }
00106   }
00107   for (iColumn=0;iColumn<numberColumns;iColumn++) {
00108     if(listNonLinearColumn[iColumn])
00109       listNonLinearColumn[numberNonLinearColumns++]=iColumn;
00110   }
00111   
00112   if (!numberNonLinearColumns) {
00113     delete [] listNonLinearColumn;
00114     // no quadratic part
00115     return primal(0);
00116   }
00117 
00118   // get feasible
00119   if (!this->status()||numberPrimalInfeasibilities())
00120     primal(1);
00121   // still infeasible
00122   if (numberPrimalInfeasibilities())
00123     return 0;
00124 
00125   int jNon;
00126   int * last[3];
00127   
00128   double * trust = new double[numberNonLinearColumns];
00129   double * trueLower = new double[numberNonLinearColumns];
00130   double * trueUpper = new double[numberNonLinearColumns];
00131   for (jNon=0;jNon<numberNonLinearColumns;jNon++) {
00132     iColumn=listNonLinearColumn[jNon];
00133     trust[jNon]=0.5;
00134     trueLower[jNon]=columnLower[iColumn];
00135     trueUpper[jNon]=columnUpper[iColumn];
00136     if (solution[iColumn]<trueLower[jNon])
00137       solution[iColumn]=trueLower[jNon];
00138     else if (solution[iColumn]>trueUpper[jNon])
00139       solution[iColumn]=trueUpper[jNon];
00140   }
00141   int iPass;
00142   double lastObjective=1.0e31;
00143   double * saveSolution = new double [numberColumns];
00144   double * savePi = new double [numberRows];
00145   unsigned char * saveStatus = new unsigned char[numberRows+numberColumns];
00146   double targetDrop=1.0e31;
00147   double objectiveOffset;
00148   getDblParam(ClpObjOffset,objectiveOffset);
00149   // 1 bound up, 2 up, -1 bound down, -2 down, 0 no change
00150   for (iPass=0;iPass<3;iPass++) {
00151     last[iPass]=new int[numberNonLinearColumns];
00152     for (jNon=0;jNon<numberNonLinearColumns;jNon++) 
00153       last[iPass][jNon]=0;
00154   }
00155   // goodMove +1 yes, 0 no, -1 last was bad - just halve gaps, -2 do nothing
00156   int goodMove=-2;
00157   char * statusCheck = new char[numberColumns];
00158   for (iPass=0;iPass<numberPasses;iPass++) {
00159     // redo objective
00160     double offset=0.0;
00161     double objValue=-objectiveOffset;
00162     double lambda=-1.0;
00163     if (goodMove>=0) {
00164       // get best interpolation 
00165       double coeff0=-objectiveOffset,coeff1=0.0,coeff2=0.0;
00166       for (iColumn=0;iColumn<numberColumns;iColumn++) {
00167         coeff0 += saveObjective[iColumn]*solution[iColumn];
00168         coeff1 += saveObjective[iColumn]*(saveSolution[iColumn]-solution[iColumn]);
00169       }
00170       for (jNon=0;jNon<numberNonLinearColumns;jNon++) {
00171         iColumn=listNonLinearColumn[jNon];
00172         double valueI = solution[iColumn];
00173         double valueISave = saveSolution[iColumn];
00174         int j;
00175         for (j=columnQuadraticStart[iColumn];
00176              j<columnQuadraticStart[iColumn]+columnQuadraticLength[iColumn];j++) {
00177           int jColumn = columnQuadratic[j];
00178           double valueJ = solution[jColumn];
00179           double valueJSave = saveSolution[jColumn];
00180           double elementValue = 0.5*quadraticElement[j];
00181           coeff0 += valueI*valueJ*elementValue;
00182           coeff1 += (valueI*valueJSave+valueISave*valueJ-2.0*valueI*valueJ)*elementValue;
00183           coeff2 += (valueISave*valueJSave+valueI*valueJ-valueISave*valueJ-valueI*valueJSave)*elementValue;
00184         }
00185       }
00186       double lambdaValue;
00187       if (fabs(coeff2)<1.0e-9) {
00188         if (coeff1+coeff2>=0.0) 
00189           lambda = 0.0;
00190         else
00191           lambda = 1.0;
00192       } else {
00193         lambda = -(0.5*coeff1)/coeff2;
00194         if (lambda>1.0||lambda<0.0) {
00195           if (coeff1+coeff2>=0.0) 
00196             lambda = 0.0;
00197           else
00198             lambda = 1.0;
00199         }
00200       }
00201       lambdaValue = lambda*lambda*coeff2+lambda*coeff1+coeff0;
00202       printf("coeffs %g %g %g - lastobj %g\n",coeff0,coeff1,coeff2,lastObjective);
00203       printf("obj at saved %g, obj now %g zero deriv at %g - value %g\n",
00204              coeff0+coeff1+coeff2,coeff0,lambda,lambdaValue);
00205       if (!iPass) lambda=0.0;
00206       if (lambda>0.0&&lambda<=1.0) {
00207         // update solution
00208         for (iColumn=0;iColumn<numberColumns;iColumn++) 
00209           solution[iColumn] = lambda * saveSolution[iColumn] 
00210             + (1.0-lambda) * solution[iColumn];
00211         if (lambda>0.999) {
00212           memcpy(this->dualRowSolution(),savePi,numberRows*sizeof(double));
00213           memcpy(status_,saveStatus,numberRows+numberColumns);
00214         }
00215         if (lambda>0.99999&&fabs(coeff1+coeff2)>1.0e-2) {
00216           // tighten all
00217           goodMove=-1;
00218         }
00219       }
00220     }
00221     memcpy(objective,saveObjective,numberColumns*sizeof(double));
00222     for (iColumn=0;iColumn<numberColumns;iColumn++) 
00223       objValue += objective[iColumn]*solution[iColumn];
00224     for (jNon=0;jNon<numberNonLinearColumns;jNon++) {
00225       iColumn=listNonLinearColumn[jNon];
00226       if (getColumnStatus(iColumn)==basic) {
00227         if (solution[iColumn]<columnLower[iColumn]+1.0e-8)
00228           statusCheck[iColumn]='l';
00229         else if (solution[iColumn]>columnUpper[iColumn]-1.0e-8)
00230           statusCheck[iColumn]='u';
00231         else
00232           statusCheck[iColumn]='B';
00233       } else {
00234         if (solution[iColumn]<columnLower[iColumn]+1.0e-8)
00235           statusCheck[iColumn]='L';
00236         else
00237           statusCheck[iColumn]='U';
00238       }
00239       double valueI = solution[iColumn];
00240       int j;
00241       for (j=columnQuadraticStart[iColumn];
00242            j<columnQuadraticStart[iColumn]+columnQuadraticLength[iColumn];j++) {
00243         int jColumn = columnQuadratic[j];
00244         double valueJ = solution[jColumn];
00245         double elementValue = quadraticElement[j];
00246         elementValue *= 0.5;
00247         objValue += valueI*valueJ*elementValue;
00248         offset += valueI*valueJ*elementValue;
00249         double gradientI = valueJ*elementValue;
00250         double gradientJ = valueI*elementValue;
00251         offset -= gradientI*valueI;
00252         objective[iColumn] += gradientI;
00253         offset -= gradientJ*valueJ;
00254         objective[jColumn] += gradientJ;
00255       }
00256     }
00257     printf("objective %g, objective offset %g\n",objValue,offset);
00258     setDblParam(ClpObjOffset,objectiveOffset-offset);
00259     objValue *= whichWay;
00260     int * temp=last[2];
00261     last[2]=last[1];
00262     last[1]=last[0];
00263     last[0]=temp;
00264     for (jNon=0;jNon<numberNonLinearColumns;jNon++) {
00265       iColumn=listNonLinearColumn[jNon];
00266       double change = solution[iColumn]-saveSolution[iColumn];
00267       if (change<-1.0e-5) {
00268         if (fabs(change+trust[jNon])<1.0e-5) 
00269           temp[jNon]=-1;
00270         else
00271           temp[jNon]=-2;
00272       } else if(change>1.0e-5) {
00273         if (fabs(change-trust[jNon])<1.0e-5) 
00274           temp[jNon]=1;
00275         else
00276           temp[jNon]=2;
00277       } else {
00278         temp[jNon]=0;
00279       }
00280     } 
00281     // goodMove +1 yes, 0 no, -1 last was bad - just halve gaps, -2 do nothing
00282     double maxDelta=0.0;
00283     if (goodMove>=0) {
00284       if (objValue<=lastObjective) 
00285         goodMove=1;
00286       else
00287         goodMove=0;
00288     } else {
00289       maxDelta=1.0e10;
00290     }
00291     double maxGap=0.0;
00292     for (jNon=0;jNon<numberNonLinearColumns;jNon++) {
00293       iColumn=listNonLinearColumn[jNon];
00294       maxDelta = max(maxDelta,
00295                      fabs(solution[iColumn]-saveSolution[iColumn]));
00296       if (goodMove>0) {
00297         if (last[0][jNon]*last[1][jNon]<0) {
00298           // halve
00299           trust[jNon] *= 0.5;
00300         } else {
00301           if (last[0][jNon]==last[1][jNon]&&
00302               last[0][jNon]==last[2][jNon])
00303             trust[jNon] *= 1.5; 
00304         }
00305       } else if (goodMove!=-2&&trust[jNon]>10.0*deltaTolerance) {
00306         trust[jNon] *= 0.2;
00307       }
00308       maxGap = max(maxGap,trust[jNon]);
00309     }
00310     std::cout<<"largest gap is "<<maxGap<<std::endl;
00311     if (iPass>10000) {
00312       for (jNon=0;jNon<numberNonLinearColumns;jNon++) 
00313         trust[jNon] *=0.0001;
00314     }
00315     if (goodMove>0) {
00316       double drop = lastObjective-objValue;
00317       std::cout<<"True drop was "<<drop<<std::endl;
00318       std::cout<<"largest delta is "<<maxDelta<<std::endl;
00319       if (maxDelta<deltaTolerance&&drop<1.0e-4&&goodMove&&lambda<0.99999) {
00320         std::cout<<"Exiting"<<std::endl;
00321         break;
00322       }
00323     }
00324     if (!iPass)
00325       goodMove=1;
00326     targetDrop=0.0;
00327     double * r = this->dualColumnSolution();
00328     for (jNon=0;jNon<numberNonLinearColumns;jNon++) {
00329       iColumn=listNonLinearColumn[jNon];
00330       columnLower[iColumn]=max(solution[iColumn]
00331                                -trust[jNon],
00332                                trueLower[jNon]);
00333       columnUpper[iColumn]=min(solution[iColumn]
00334                                +trust[jNon],
00335                                trueUpper[jNon]);
00336     }
00337     if (iPass) {
00338       // get reduced costs
00339       this->matrix()->transposeTimes(savePi,
00340                                      this->dualColumnSolution());
00341       for (jNon=0;jNon<numberNonLinearColumns;jNon++) {
00342         iColumn=listNonLinearColumn[jNon];
00343         double dj = objective[iColumn]-r[iColumn];
00344         r[iColumn]=dj;
00345         if (dj<0.0) 
00346           targetDrop -= dj*(columnUpper[iColumn]-solution[iColumn]);
00347         else
00348           targetDrop -= dj*(columnLower[iColumn]-solution[iColumn]);
00349       }
00350     } else {
00351       memset(r,0,numberColumns*sizeof(double));
00352     }
00353 #if 0
00354     for (jNon=0;jNon<numberNonLinearColumns;jNon++) {
00355       iColumn=listNonLinearColumn[jNon];
00356       if (statusCheck[iColumn]=='L'&&r[iColumn]<-1.0e-4) {
00357         columnLower[iColumn]=max(solution[iColumn],
00358                                  trueLower[jNon]);
00359         columnUpper[iColumn]=min(solution[iColumn]
00360                                  +trust[jNon],
00361                                  trueUpper[jNon]);
00362       } else if (statusCheck[iColumn]=='U'&&r[iColumn]>1.0e-4) {
00363         columnLower[iColumn]=max(solution[iColumn]
00364                                  -trust[jNon],
00365                                  trueLower[jNon]);
00366         columnUpper[iColumn]=min(solution[iColumn],
00367                                  trueUpper[jNon]);
00368       } else {
00369         columnLower[iColumn]=max(solution[iColumn]
00370                                  -trust[jNon],
00371                                  trueLower[jNon]);
00372         columnUpper[iColumn]=min(solution[iColumn]
00373                                  +trust[jNon],
00374                                  trueUpper[jNon]);
00375       }
00376     }
00377 #endif
00378     if (goodMove) {
00379       memcpy(saveSolution,solution,numberColumns*sizeof(double));
00380       memcpy(savePi,this->dualRowSolution(),numberRows*sizeof(double));
00381       memcpy(saveStatus,status_,numberRows+numberColumns);
00382       
00383       std::cout<<"Pass - "<<iPass
00384                <<", target drop is "<<targetDrop
00385                <<std::endl;
00386       lastObjective = objValue;
00387       if (targetDrop<1.0e-5&&goodMove&&iPass) {
00388         printf("Exiting on target drop %g\n",targetDrop);
00389         break;
00390       }
00391       {
00392         double * r = this->dualColumnSolution();
00393         for (jNon=0;jNon<numberNonLinearColumns;jNon++) {
00394           iColumn=listNonLinearColumn[jNon];
00395           printf("Trust %d %g - solution %d %g obj %g dj %g state %c - bounds %g %g\n",
00396                  jNon,trust[jNon],iColumn,solution[iColumn],objective[iColumn],
00397                  r[iColumn],statusCheck[iColumn],columnLower[iColumn],
00398                  columnUpper[iColumn]);
00399         }
00400       }
00401       setLogLevel(63);
00402       this->scaling(false);
00403       this->primal(1);
00404       if (this->status()) {
00405         CoinMpsIO writer;
00406         writer.setMpsData(*matrix(), COIN_DBL_MAX,
00407                           getColLower(), getColUpper(),
00408                           getObjCoefficients(),
00409                           (const char*) 0 /*integrality*/,
00410                           getRowLower(), getRowUpper(),
00411                           NULL,NULL);
00412         writer.writeMps("xx.mps");
00413       }
00414       assert (!this->status()); // must be feasible
00415       goodMove=1;
00416     } else {
00417       // bad pass - restore solution
00418       printf("Backtracking\n");
00419       memcpy(solution,saveSolution,numberColumns*sizeof(double));
00420       memcpy(this->dualRowSolution(),savePi,numberRows*sizeof(double));
00421       memcpy(status_,saveStatus,numberRows+numberColumns);
00422       iPass--;
00423       goodMove=-1;
00424     }
00425   }
00426   // restore solution
00427   memcpy(solution,saveSolution,numberColumns*sizeof(double));
00428   for (jNon=0;jNon<numberNonLinearColumns;jNon++) {
00429     iColumn=listNonLinearColumn[jNon];
00430     columnLower[iColumn]=max(solution[iColumn],
00431                              trueLower[jNon]);
00432     columnUpper[iColumn]=min(solution[iColumn],
00433                              trueUpper[jNon]);
00434   }
00435   delete [] statusCheck;
00436   delete [] savePi;
00437   delete [] saveStatus;
00438   // redo objective
00439   double offset=0.0;
00440   double objValue=-objectiveOffset;
00441   memcpy(objective,saveObjective,numberColumns*sizeof(double));
00442   for (iColumn=0;iColumn<numberColumns;iColumn++) 
00443     objValue += objective[iColumn]*solution[iColumn];
00444   for (jNon=0;jNon<numberNonLinearColumns;jNon++) {
00445     iColumn=listNonLinearColumn[jNon];
00446     double valueI = solution[iColumn];
00447     int j;
00448     for (j=columnQuadraticStart[iColumn];
00449          j<columnQuadraticStart[iColumn]+columnQuadraticLength[iColumn];j++) {
00450       int jColumn = columnQuadratic[j];
00451       double valueJ = solution[jColumn];
00452       double elementValue = quadraticElement[j];
00453       objValue += 0.5*valueI*valueJ*elementValue;
00454       offset += 0.5*valueI*valueJ*elementValue;
00455       double gradientI = valueJ*elementValue;
00456       double gradientJ = valueI*elementValue;
00457       offset -= gradientI*valueI;
00458       objective[iColumn] += gradientI;
00459       offset -= gradientJ*valueJ;
00460       objective[jColumn] += gradientJ;
00461     }
00462   }
00463   printf("objective %g, objective offset %g\n",objValue,offset);
00464   setDblParam(ClpObjOffset,objectiveOffset-offset);
00465   this->primal(1);
00466   // redo values
00467   setDblParam(ClpObjOffset,objectiveOffset);
00468   objectiveValue_ += whichWay*offset;
00469   for (jNon=0;jNon<numberNonLinearColumns;jNon++) {
00470     iColumn=listNonLinearColumn[jNon];
00471     columnLower[iColumn]= trueLower[jNon];
00472     columnUpper[iColumn]= trueUpper[jNon];
00473   }
00474   memcpy(objective,saveObjective,numberColumns*sizeof(double));
00475   delete [] saveSolution;
00476   for (iPass=0;iPass<3;iPass++) 
00477     delete [] last[iPass];
00478   delete [] trust;
00479   delete [] trueUpper;
00480   delete [] trueLower;
00481   delete [] saveObjective;
00482   delete [] listNonLinearColumn;
00483   return 0;
00484 }
00485 // Dantzig's method
00486 int 
00487 ClpSimplexPrimalQuadratic::primalQuadratic(int phase)
00488 {
00489   // Get a feasible solution 
00490   if (numberPrimalInfeasibilities())
00491     primal(1);
00492   // still infeasible
00493   if (numberPrimalInfeasibilities())
00494     return 1;
00495   ClpQuadraticInfo info;
00496   ClpSimplexPrimalQuadratic * model2 = makeQuadratic(info);
00497   if (!model2) {
00498     printf("** Not quadratic\n");
00499     primal(1);
00500     return 0;
00501   }
00502 #if 0
00503   CoinMpsIO writer;
00504   writer.setMpsData(*model2->matrix(), COIN_DBL_MAX,
00505                     model2->getColLower(), model2->getColUpper(),
00506                     model2->getObjCoefficients(),
00507                     (const char*) 0 /*integrality*/,
00508                     model2->getRowLower(), model2->getRowUpper(),
00509                     NULL,NULL);
00510   writer.writeMps("xx.mps");
00511 #endif  
00512   // Now do quadratic
00513   //ClpPrimalQuadraticDantzig dantzigP(model2,&info);
00514   ClpPrimalColumnDantzig dantzigP;
00515   model2->setPrimalColumnPivotAlgorithm(dantzigP);
00516   model2->messageHandler()->setLogLevel(63);
00517   model2->primalQuadratic2(&info,phase);
00518   endQuadratic(model2,info);
00519   return 0;
00520 }
00521 int ClpSimplexPrimalQuadratic::primalQuadratic2 (ClpQuadraticInfo * info,
00522                                                  int phase)
00523 {
00524 
00525   algorithm_ = +2;
00526 
00527   // save data
00528   ClpDataSave data = saveData();
00529   // Only ClpPackedMatrix at present
00530   assert ((dynamic_cast< ClpPackedMatrix*>(matrix_)));
00531   
00532   // Assume problem is feasible
00533   // Stuff below will be moved into a class
00534   int numberXColumns = info->numberXColumns();
00535   int numberXRows = info->numberXRows();
00536   // initialize - values pass coding and algorithm_ is +1
00537   ClpObjective * saveObj = objectiveAsObject();
00538   setObjectivePointer(info->originalObjective());
00539   factorization_->setBiasLU(0);
00540   if (!startup(1)) {
00541 
00542     //setObjectivePointer(saveObj);
00543     // Setup useful stuff
00544     info->setCurrentPhase(phase);
00545     int lastCleaned=0; // last time objective or bounds cleaned up
00546     info->setSequenceIn(-1);
00547     info->setCrucialSj(-1);
00548     bool deleteCosts=false;
00549     if (scalingFlag_>0) {
00550       // scale
00551       CoinPackedMatrix * quadratic = info->quadraticObjective();
00552       double * objective = info->linearObjective();
00553       // replace column by column
00554       double * newElement = new double[numberXColumns];
00555       // scale column copy
00556       // get matrix data pointers
00557       const int * row = quadratic->getIndices();
00558       const CoinBigIndex * columnStart = quadratic->getVectorStarts();
00559       const int * columnLength = quadratic->getVectorLengths(); 
00560       const double * elementByColumn = quadratic->getElements();
00561       double direction = optimizationDirection_;
00562       // direction is actually scale out not scale in
00563       if (direction)
00564         direction = 1.0/direction;
00565       int iColumn;
00566       for (iColumn=0;iColumn<numberXColumns;iColumn++) {
00567         int j;
00568         double scale = columnScale_[iColumn]*direction;
00569         const double * elementsInThisColumn = elementByColumn + columnStart[iColumn];
00570         const int * columnsInThisColumn = row + columnStart[iColumn];
00571         int number = columnLength[iColumn];
00572         assert (number<=numberXColumns);
00573         for (j=0;j<number;j++) {
00574           int iColumn2 = columnsInThisColumn[j];
00575           newElement[j] = elementsInThisColumn[j]*scale*rowScale_[iColumn2+numberXRows];
00576         }
00577         quadratic->replaceVector(iColumn,number,newElement);
00578         objective[iColumn] *= direction*columnScale_[iColumn];
00579       }
00580       delete [] newElement;
00581       deleteCosts=true;
00582     } else if (optimizationDirection_!=1.0) {
00583       CoinPackedMatrix * quadratic = info->quadraticObjective();
00584       double * objective = info->linearObjective();
00585       // replace column by column
00586       double * newElement = new double[numberXColumns];
00587       // get matrix data pointers
00588       const CoinBigIndex * columnStart = quadratic->getVectorStarts();
00589       const int * columnLength = quadratic->getVectorLengths(); 
00590       const double * elementByColumn = quadratic->getElements();
00591       double direction = optimizationDirection_;
00592       // direction is actually scale out not scale in
00593       if (direction)
00594         direction = 1.0/direction;
00595       int iColumn;
00596       for (iColumn=0;iColumn<numberXColumns;iColumn++) {
00597         int j;
00598         const double * elementsInThisColumn = elementByColumn + columnStart[iColumn];
00599         int number = columnLength[iColumn];
00600         assert (number<=numberXColumns);
00601         for (j=0;j<number;j++) {
00602           newElement[j] = elementsInThisColumn[j]*direction;
00603         }
00604         quadratic->replaceVector(iColumn,number,newElement);
00605         objective[iColumn] *= direction;
00606       }
00607       delete [] newElement;
00608       deleteCosts=true;
00609     }
00610     
00611     // Say no pivot has occurred (for steepest edge and updates)
00612     pivotRow_=-2;
00613     
00614     // This says whether to restore things etc
00615     int factorType=0;
00616     /*
00617       Status of problem:
00618       0 - optimal
00619       1 - infeasible
00620       2 - unbounded
00621       -1 - iterating
00622       -2 - factorization wanted
00623       -3 - redo checking without factorization
00624       -4 - looks infeasible
00625       -5 - looks unbounded
00626     */
00627     while (problemStatus_<0) {
00628       int iRow,iColumn;
00629       // clear
00630       for (iRow=0;iRow<4;iRow++) {
00631         rowArray_[iRow]->clear();
00632       }    
00633       
00634       for (iColumn=0;iColumn<2;iColumn++) {
00635         columnArray_[iColumn]->clear();
00636       }    
00637       
00638       // give matrix (and model costs and bounds a chance to be
00639       // refreshed (normally null)
00640       matrix_->refresh(this);
00641       // If we have done no iterations - special
00642       if (lastGoodIteration_==numberIterations_)
00643         factorType=3;
00644       // may factorize, checks if problem finished
00645       statusOfProblemInPrimal(lastCleaned,factorType,progress_,info);
00646       if (problemStatus_>=0)
00647         break; // declare victory
00648       
00649       checkComplementarity (info,rowArray_[0],rowArray_[1]);
00650 
00651       // Say good factorization
00652       factorType=1;
00653       
00654       // Say no pivot has occurred (for steepest edge and updates)
00655       pivotRow_=-2;
00656       // Check problem phase 
00657       // We assume all X are feasible
00658       if (info->currentSolution()&&info->sequenceIn()<0) {
00659         phase=0;
00660         int nextSequenceIn=-1;
00661         int numberQuadraticRows = info->numberQuadraticRows();
00662         for (iColumn=0;iColumn<numberXColumns;iColumn++) {
00663           double value = solution_[iColumn];
00664           double lower = lower_[iColumn];
00665           double upper = upper_[iColumn];
00666           if ((value>lower+primalTolerance_&&value<upper-primalTolerance_)
00667               ||getColumnStatus(iColumn)==superBasic) {
00668             if (getColumnStatus(iColumn)!=basic&&!flagged(iColumn)) {
00669               if (fabs(dj_[iColumn])>10.0*dualTolerance_||
00670                   getColumnStatus(iColumn+numberXColumns+numberQuadraticRows)==basic) {
00671                 if (phase!=2) {
00672                   phase=2;
00673                   nextSequenceIn=iColumn;
00674                 }
00675               }
00676             }
00677           }
00678         }
00679         for (iColumn=numberColumns_;iColumn<numberColumns_+numberXRows;iColumn++) {
00680           double value = solution_[iColumn];
00681           double lower = lower_[iColumn];
00682           double upper = upper_[iColumn];
00683           if ((value>lower+primalTolerance_&&value<upper-primalTolerance_)
00684             ||getColumnStatus(iColumn)==superBasic) {
00685             if (getColumnStatus(iColumn)!=basic&&!flagged(iColumn)&&fabs(dj_[iColumn])>10.0*dualTolerance_) {
00686               if (phase!=2) {
00687                 phase=2;
00688                 nextSequenceIn=iColumn;
00689               }
00690             }
00691           }
00692         }
00693         info->setSequenceIn(nextSequenceIn);
00694         info->setCurrentPhase(phase);
00695       }
00696 
00697       // exit if victory declared
00698       dualIn_=0.0; // so no updates
00699       if (!info->currentPhase()&&info->sequenceIn()<0&&primalColumnPivot_->pivotColumn(rowArray_[1],
00700                                           rowArray_[2],rowArray_[3],
00701                                           columnArray_[0],
00702                                           columnArray_[1]) < 0) {
00703         problemStatus_=0;
00704         break;
00705       }
00706       
00707       // Iterate
00708       problemStatus_=-1;
00709       whileIterating(info);
00710     }
00711     if (deleteCosts) {
00712       // delete scaled copy of objective
00713       delete info->originalObjective();
00714     }
00715   }
00716   setObjectivePointer(saveObj);
00717   // clean up
00718   finish();
00719   restoreData(data);
00720   return problemStatus_;
00721 }
00722 /*
00723   Reasons to come out:
00724   -1 iterations etc
00725   -2 inaccuracy 
00726   -3 slight inaccuracy (and done iterations)
00727   -4 end of values pass and done iterations
00728   +0 looks optimal (might be infeasible - but we will investigate)
00729   +2 looks unbounded
00730   +3 max iterations 
00731 */
00732 int
00733 ClpSimplexPrimalQuadratic::whileIterating(
00734                       ClpQuadraticInfo * info)
00735 {
00736   checkComplementarity (info,rowArray_[0],rowArray_[1]);
00737   int crucialSj = info->crucialSj();
00738   if (info->crucialSj()>=0) {
00739     printf("after inv %d Sj value %g\n",crucialSj,solution_[info->crucialSj()]);
00740   }
00741   int returnCode=-1;
00742   int phase = info->currentPhase();
00743   double saveObjective = objectiveValue_;
00744   int numberXColumns = info->numberXColumns();
00745   int numberXRows = info->numberXRows();
00746   int numberQuadraticRows = info->numberQuadraticRows();
00747   // Make list of implied sj
00748   // And backward pointers to basic variables
00749   {
00750     int * impliedSj = info->impliedSj();
00751     int i;
00752     for (i=numberRows_;i<numberColumns_;i++) {
00753       if (getColumnStatus(i)==basic)
00754         impliedSj[i-numberRows_]=i;
00755       else
00756         impliedSj[i-numberRows_]=-1;
00757     }
00758     int * basicRow = info->basicRow();
00759     for (i=0;i<numberRows_+numberColumns_;i++)
00760       basicRow[i]=-1;
00761     for (i=0;i<numberRows_;i++)
00762       basicRow[pivotVariable_[i]]=i;
00763   }
00764   int nextSequenceIn=info->sequenceIn();
00765   int oldSequenceIn=nextSequenceIn;
00766   int saveSequenceIn = sequenceIn_;
00767   // status stays at -1 while iterating, >=0 finished, -2 to invert
00768   // status -3 to go to top without an invert
00769   while (problemStatus_==-1) {
00770     if (info->crucialSj()<0&&factorization_->pivots()>=10) {
00771       returnCode =-2; // refactorize
00772       break;
00773     }
00774 #ifdef CLP_DEBUG
00775     {
00776       int i;
00777       // not [1] as has information
00778       for (i=0;i<4;i++) {
00779         if (i!=1)
00780           rowArray_[i]->checkClear();
00781       }    
00782       for (i=0;i<2;i++) {
00783         columnArray_[i]->checkClear();
00784       }    
00785     }      
00786 #endif
00787     // choose column to come in
00788     // can use pivotRow_ to update weights
00789     // pass in list of cost changes so can do row updates (rowArray_[1])
00790     // NOTE rowArray_[0] is used by computeDuals which is a 
00791     // slow way of getting duals but might be used 
00792     // Initially Dantzig and look at s variables
00793     // Only do if one not already chosen
00794     int cleanupIteration;
00795     if (nextSequenceIn<0) {
00796       cleanupIteration=0;
00797       if (phase==2) {
00798         // values pass
00799         // get next
00800         int iColumn;
00801         int iStart = oldSequenceIn+1;
00802         for (iColumn=iStart;iColumn<numberXColumns;iColumn++) {
00803           double value = solution_[iColumn];
00804           double lower = lower_[iColumn];
00805           double upper = upper_[iColumn];
00806           if (value>lower+primalTolerance_&&value<upper-primalTolerance_) {
00807             if (getColumnStatus(iColumn)!=basic&&!flagged(iColumn)) {
00808               if (fabs(dj_[iColumn])>10.0*dualTolerance_||
00809                   getColumnStatus(iColumn+numberXColumns+numberQuadraticRows)==basic) {
00810                 nextSequenceIn=iColumn;
00811                 break;
00812               }
00813             }
00814           }
00815         }
00816         if (nextSequenceIn<0) {
00817           iStart=max(iStart,numberColumns_);
00818           int numberXRows = info->numberXRows();
00819           for (iColumn=iStart;iColumn<numberColumns_+numberXRows;
00820                iColumn++) {
00821             double value = solution_[iColumn];
00822             double lower = lower_[iColumn];
00823             double upper = upper_[iColumn];
00824             if (value>lower+primalTolerance_&&value<upper-primalTolerance_) {
00825               if (getColumnStatus(iColumn)!=basic&&!flagged(iColumn)&&fabs(dj_[iColumn])>10.0*dualTolerance_) {
00826                 nextSequenceIn=iColumn;
00827                 break;
00828               }
00829             }
00830           }
00831         }
00832         oldSequenceIn=nextSequenceIn;
00833         saveSequenceIn=sequenceIn_;
00834         sequenceIn_ = nextSequenceIn;
00835       } else {
00836         saveSequenceIn=sequenceIn_;
00837         createDjs(info,rowArray_[3],rowArray_[2]);
00838         dualIn_=0.0; // so no updates
00839         rowArray_[1]->clear();
00840         primalColumn(rowArray_[1],rowArray_[2],rowArray_[3],
00841                      columnArray_[0],columnArray_[1]);
00842       }
00843     } else {
00844       saveSequenceIn=sequenceIn_;
00845       sequenceIn_ = nextSequenceIn;
00846       if (phase==2) {
00847         if ((sequenceIn_<numberXColumns||sequenceIn_>=numberColumns_)&&info->crucialSj()<0) 
00848           cleanupIteration=0;
00849         else
00850           cleanupIteration=1;
00851       } else {
00852         cleanupIteration=1;
00853       }
00854     }
00855     pivotRow_=-1;
00856     sequenceOut_=-1;
00857     rowArray_[1]->clear();
00858     if (sequenceIn_>=0) {
00859       nextSequenceIn=-1;
00860       // we found a pivot column
00861       int chosen = sequenceIn_;
00862       // do second half of iteration
00863       while (chosen>=0) {
00864         int saveSequenceInInfo=chosen;
00865         int saveCrucialSjInfo=info->crucialSj();
00866         rowArray_[1]->clear();
00867         checkComplementarity (info,rowArray_[3],rowArray_[1]);
00868         printf("True objective is %g, infeas cost %g, sum %g\n",
00869                objectiveValue_,info->infeasCost(),objectiveValue_+info->infeasCost());
00870         objectiveValue_=saveObjective;
00871         returnCode=-1;
00872         pivotRow_=-1;
00873         sequenceOut_=-1;
00874         // we found a pivot column
00875         // update the incoming column
00876         sequenceIn_=chosen;
00877         chosen=-1;
00878         unpack(rowArray_[1]);
00879         // compute dj in case linear
00880         {
00881           info->createGradient(this);
00882           double * gradient = info->gradient();
00883           dualIn_=gradient[sequenceIn_];
00884           int j;
00885           const double * element = rowArray_[1]->denseVector();
00886           int numberNonZero=rowArray_[1]->getNumElements();
00887           const int * whichRow = rowArray_[1]->getIndices();
00888           bool packed = rowArray_[1]->packedMode();
00889           if (packed) {
00890             for (j=0;j<numberNonZero; j++) {
00891               int iRow = whichRow[j];
00892               dualIn_ -= element[j]*dual_[iRow];
00893             }
00894           } else {
00895             for (j=0;j<numberNonZero; j++) {
00896               int iRow = whichRow[j];
00897               dualIn_ -= element[iRow]*dual_[iRow];
00898             }
00899           }
00900         }
00901         if ((!cleanupIteration&&sequenceIn_<numberXColumns)||
00902             (cleanupIteration&&info->crucialSj()<numberColumns_&&info->crucialSj()>=numberRows_)) {
00903           int iSequence;
00904           if (!cleanupIteration)
00905             iSequence=sequenceIn_;
00906           else
00907             iSequence=info->crucialSj()-numberRows_;
00908           // may need to re-do row of basis
00909           int * impliedSj = info->impliedSj();
00910           if (impliedSj[iSequence]>=0) {
00911             // mark as valid
00912             impliedSj[iSequence]=-1;
00913             ClpPackedMatrix* rowCopy =
00914               dynamic_cast< ClpPackedMatrix*>(rowCopy_);
00915             assert(rowCopy);
00916             const int * column = rowCopy->getIndices();
00917             const CoinBigIndex * rowStart = rowCopy->getVectorStarts();
00918             const double * rowElement = rowCopy->getElements();
00919             int iRow=iSequence+numberXRows;
00920             int i;
00921             int * index = rowArray_[2]->getIndices();
00922             double * element = rowArray_[2]->denseVector();
00923             int n=0;
00924             int * basicRow = info->basicRow();
00925             int * permute = factorization_->pivotColumn();
00926             for (i=rowStart[iRow];i<rowStart[iRow+1];i++) {
00927               int iColumn = column[i];
00928               iColumn = basicRow[iColumn];
00929               if (iColumn>=0&&iColumn!=iRow) {
00930                 index[n]=permute[iColumn];
00931                 element[n++]=rowElement[i];
00932               }
00933             }
00934             factorization_->replaceRow(permute[iRow],n,index,element);
00935             memset(element,0,n*sizeof(double));
00936           }
00937         }
00938         // Take out elements in implied Sj rows
00939         if (1) { 
00940           int n=rowArray_[1]->getNumElements();
00941           int * index = rowArray_[1]->getIndices();
00942           double * element = rowArray_[1]->denseVector();
00943           int i;
00944           int * impliedSj = info->impliedSj();
00945           int n2=0;
00946           for (i=0;i<n;i++) {
00947             int iRow=index[i]-numberXRows;
00948             if (iRow<0||impliedSj[iRow]<0) {
00949               index[n2++]=iRow+numberXRows;
00950             } else {
00951               element[iRow+numberXRows]=0.0;
00952             }
00953           }
00954           rowArray_[1]->setNumElements(n2);
00955         }
00956         factorization_->updateColumnFT(rowArray_[2],rowArray_[1]);
00957         if (cleanupIteration) {
00958           // move back to a version of primalColumn?
00959           valueIn_=solution_[sequenceIn_];
00960           // should keep pivot row of crucialSj as well (speed)
00961           int iSjRow=-1;
00962           if (crucialSj>=0) {
00963             double * work=rowArray_[1]->denseVector();
00964             int number=rowArray_[1]->getNumElements();
00965             int * which=rowArray_[1]->getIndices();
00966             double tj = 0.0;
00967             int iIndex;
00968             for (iIndex=0;iIndex<number;iIndex++) {
00969               int iRow = which[iIndex];
00970               double alpha = work[iRow];
00971               int iPivot=pivotVariable_[iRow];
00972               if (iPivot==crucialSj) {
00973                 tj = alpha;
00974                 iSjRow = iRow;
00975                 double d2 = solution_[crucialSj]/tj;
00976                 if (fabs(solution_[crucialSj])<1.0e-8)
00977                   printf("zero crucialSj - pivot out - get right way\n");
00978                 // see which way to go
00979                 if (d2>0)
00980                   dj_[sequenceIn_]= -1.0;
00981                 else
00982                   dj_[sequenceIn_]= 1.0;
00983                 break;
00984               }
00985             }
00986             if (!tj) {
00987               printf("trouble\n");
00988               assert (sequenceIn_>numberXColumns&&sequenceIn_<numberColumns_);
00989               dj_[sequenceIn_]=solution_[sequenceIn_];
00990             //assert(tj);
00991             }
00992           }
00993 
00994           dualIn_=dj_[sequenceIn_];
00995           lowerIn_=lower_[sequenceIn_];
00996           upperIn_=upper_[sequenceIn_];
00997           if (dualIn_>0.0)
00998             directionIn_ = -1;
00999           else 
01000             directionIn_ = 1;
01001         } else {
01002           // not clean up
01003           lowerIn_=lower_[sequenceIn_];
01004           upperIn_=upper_[sequenceIn_];
01005           dualIn_=dj_[sequenceIn_];
01006           valueIn_=solution_[sequenceIn_];
01007           if (dualIn_>0.0)
01008             directionIn_ = -1;
01009           else 
01010             directionIn_ = 1;
01011           if (sequenceIn_<numberColumns_) {
01012             // Set dj as value of slack
01013             crucialSj = sequenceIn_+ numberQuadraticRows+numberXColumns; // sj which should go to 0.0
01014           } else {
01015             // Set dj as value of pi
01016             int iRow = sequenceIn_-numberColumns_;
01017             crucialSj = iRow+numberXColumns; // pi which should go to 0.0
01018           }
01019           if (crucialSj>=0&&getColumnStatus(crucialSj)!=basic)
01020             crucialSj=-1;
01021           info->setCrucialSj(crucialSj);
01022         }
01023         double oldSj=1.0e30;
01024         if (info->crucialSj()>=0&&cleanupIteration)
01025           oldSj= solution_[info->crucialSj()];
01026         // save reduced cost
01027         //double saveDj = dualIn_;
01028         // do ratio test and re-compute dj
01029         // Note second parameter long enough for columns
01030         int result=primalRow(rowArray_[1],rowArray_[3],
01031                              rowArray_[2],rowArray_[0],
01032                              info,
01033                              cleanupIteration);
01034         if (pivotRow_==-1&&(phase==2||cleanupIteration)&&fabs(dualIn_)<1.0e-3) {
01035           // try other way
01036           dualIn_=-dualIn_;
01037           directionIn_=-directionIn_;
01038           if (info->crucialSj()>=0)
01039             setColumnStatus(info->crucialSj(),basic);
01040           result=primalRow(rowArray_[1],rowArray_[3],
01041                            rowArray_[2],rowArray_[0],
01042                            info,
01043                            cleanupIteration);
01044         }
01045         saveObjective = objectiveValue_;
01046         if (pivotRow_>=0) {
01047           // If sj out AND not gone out since last invert then add back
01048           // if stable replace in basis
01049           int updateStatus = 0;
01050           if (result<20) {
01051             double saveCheck = factorization_->getAccuracyCheck();
01052             if (cleanupIteration)
01053               factorization_->relaxAccuracyCheck(1.0e3*saveCheck);
01054             updateStatus=factorization_->replaceColumn(rowArray_[2],
01055                                                        pivotRow_,
01056                                                        alpha_);
01057             factorization_->relaxAccuracyCheck(saveCheck);
01058           }
01059           if (result>=10) {
01060             updateStatus = max(updateStatus,result/10);
01061             result = result%10;
01062             if (updateStatus>1) {
01063               alpha_=0.0; // force re-factorization
01064               info->setSequenceIn(sequenceIn_);
01065             }
01066           }
01067           // if no pivots, bad update but reasonable alpha - take and invert
01068           if (updateStatus==2&&
01069               lastGoodIteration_==numberIterations_&&fabs(alpha_)>1.0e-5)
01070             updateStatus=4;
01071           if (updateStatus==1||updateStatus==4) {
01072             // slight error
01073             if (factorization_->pivots()>5||updateStatus==4) {
01074               returnCode=-3;
01075             }
01076           } else if (updateStatus==2) {
01077             // major error
01078             // Reset sequenceIn_
01079             // sequenceIn_=saveSequenceIn;
01080             nextSequenceIn=saveSequenceInInfo;
01081             info->setCrucialSj(saveCrucialSjInfo);
01082             if (saveCrucialSjInfo<0&&!phase)
01083               nextSequenceIn=-1;
01084             pivotRow_=-1;
01085             // better to have small tolerance even if slower
01086             factorization_->zeroTolerance(1.0e-15);
01087             int maxFactor = factorization_->maximumPivots();
01088             if (maxFactor>10) {
01089               if (forceFactorization_<0)
01090                 forceFactorization_= maxFactor;
01091               forceFactorization_ = max (1,(forceFactorization_>>1));
01092             } 
01093             // later we may need to unwind more e.g. fake bounds
01094             if(lastGoodIteration_ != numberIterations_||factorization_->pivots()) {
01095               rowArray_[1]->clear();
01096               pivotRow_=-1;
01097               returnCode=-4;
01098               // retry on return
01099               if (info->crucialSj()>=0)
01100                 nextSequenceIn = sequenceIn_;
01101               break;
01102             } else {
01103               // need to reject something
01104               char x = isColumn(sequenceIn_) ? 'C' :'R';
01105               handler_->message(CLP_SIMPLEX_FLAG,messages_)
01106                 <<x<<sequenceWithin(sequenceIn_)
01107                 <<CoinMessageEol;
01108               setFlagged(sequenceIn_);
01109               lastBadIteration_ = numberIterations_; // say be more cautious
01110               rowArray_[1]->clear();
01111               pivotRow_=-1;
01112               returnCode = -5;
01113               break;
01114               
01115             }
01116           } else if (updateStatus==3) {
01117             // out of memory
01118             // increase space if not many iterations
01119             if (factorization_->pivots()<
01120                 0.5*factorization_->maximumPivots()&&
01121                 factorization_->pivots()<200)
01122               factorization_->areaFactor(
01123                                          factorization_->areaFactor() * 1.1);
01124             returnCode =-2; // factorize now
01125           }
01126           // here do part of steepest - ready for next iteration
01127           primalColumnPivot_->updateWeights(rowArray_[1]);
01128         } else {
01129           if (pivotRow_==-1) {
01130             // no outgoing row is valid
01131             rowArray_[0]->clear();
01132             if (!factorization_->pivots()) {
01133               returnCode = 2; //say looks unbounded
01134               // do ray
01135               primalRay(rowArray_[1]);
01136             } else {
01137               returnCode = 4; //say looks unbounded but has iterated
01138             }
01139             break;
01140           } else {
01141             // flipping from bound to bound
01142           }
01143         }
01144 
01145 
01146         // update primal solution
01147 
01148         double objectiveChange=0.0;
01149         // Cost on pivot row may change - may need to change dualIn
01150         double oldCost=0.0;
01151         if (pivotRow_>=0)
01152           oldCost = cost(pivotVariable_[pivotRow_]);
01153         // rowArray_[1] is not empty - used to update djs
01154         updatePrimalsInPrimal(rowArray_[1],theta_, objectiveChange,1);
01155         if (pivotRow_>=0)
01156           dualIn_ += (oldCost-cost(pivotVariable_[pivotRow_]));
01157         double oldValue = valueIn_;
01158         if (directionIn_==-1) {
01159           // as if from upper bound
01160           if (sequenceIn_!=sequenceOut_) {
01161             // variable becoming basic
01162             valueIn_ -= fabs(theta_);
01163           } else {
01164             valueIn_=lowerIn_;
01165           }
01166         } else {
01167           // as if from lower bound
01168           if (sequenceIn_!=sequenceOut_) {
01169             // variable becoming basic
01170             valueIn_ += fabs(theta_);
01171           } else {
01172             valueIn_=upperIn_;
01173           }
01174         }
01175         objectiveChange += dualIn_*(valueIn_-oldValue);
01176         // outgoing
01177         if (sequenceIn_!=sequenceOut_) {
01178           if (directionOut_>0) {
01179             valueOut_ = lowerOut_;
01180           } else {
01181             valueOut_ = upperOut_;
01182           }
01183           double lowerValue = lower_[sequenceOut_];
01184           double upperValue = upper_[sequenceOut_];
01185           if (sequenceOut_>=numberXColumns&&sequenceOut_<numberColumns_) {
01186             // really free but going to zero
01187             lowerValue=0.0;
01188             upperValue=0.0;
01189           }
01190           assert(valueOut_>=lowerValue-primalTolerance_&&
01191                  valueOut_<=upperValue+primalTolerance_);
01192           // may not be exactly at bound and bounds may have changed
01193 #if 1
01194           // Make sure outgoing looks feasible
01195           double useValue=valueOut_;
01196           if (valueOut_<=lowerValue+primalTolerance_) {
01197             directionOut_=1;
01198             useValue= lower_[sequenceOut_];
01199           } else if (valueOut_>=upperValue-primalTolerance_) {
01200             directionOut_=-1;
01201             useValue= upper_[sequenceOut_];
01202           } else {
01203             printf("*** variable wandered off bound %g %g %g!\n",
01204                    lowerValue,valueOut_,upperValue);
01205             if (valueOut_-lowerValue<=upperValue-valueOut_) {
01206               useValue= lower_[sequenceOut_];
01207               valueOut_=lowerValue;
01208               directionOut_=1;
01209             } else {
01210               useValue= upper_[sequenceOut_];
01211               valueOut_=upperValue;
01212               directionOut_=-1;
01213             }
01214           }
01215           solution_[sequenceOut_]=valueOut_;
01216           nonLinearCost_->setOne(sequenceOut_,useValue);
01217 #else
01218           directionOut_=nonLinearCost_->setOneOutgoing(sequenceOut_,valueOut_);
01219           solution_[sequenceOut_]=valueOut_;
01220 #endif
01221         }
01222         // change cost and bounds on incoming if primal
01223         if (sequenceIn_==sequenceOut_&&(lowerOut_!=lowerIn_||upperOut_!=upperIn_)) {
01224           // linear variable superbasic
01225           setStatus(sequenceOut_,superBasic);
01226         }
01227         nonLinearCost_->setOne(sequenceIn_,valueIn_); 
01228         int whatNext=housekeeping(objectiveChange);
01229         // and again as housekeeping may have changed
01230         if (sequenceIn_==sequenceOut_&&(lowerOut_!=lowerIn_||upperOut_!=upperIn_)) {
01231           // linear variable superbasic
01232           setStatus(sequenceOut_,superBasic);
01233         }
01234         // And update backward pointers to basic variables
01235         if (sequenceIn_!=sequenceOut_) {
01236           int * basicRow = info->basicRow();
01237           basicRow[sequenceOut_]=-1;
01238           basicRow[sequenceIn_]=pivotRow_;
01239         }
01240         if (info->crucialSj()>=0) {
01241           assert(fabs(oldSj)>= fabs(solution_[info->crucialSj()]));
01242           printf("%d Sj value went from %g to %g\n",crucialSj,oldSj,solution_[info->crucialSj()]);
01243         }
01244         checkComplementarity (info,rowArray_[2],rowArray_[3]);
01245         printf("After Housekeeping True objective is %g, infeas cost %g, sum %g\n",
01246                objectiveValue_,info->infeasCost(),objectiveValue_+info->infeasCost());
01247         if (sequenceOut_>=numberXColumns&&sequenceOut_<numberColumns_) {
01248           // really free but going to zero
01249           setStatus(sequenceOut_,isFree);
01250           if (sequenceOut_==info->crucialSj())
01251             info->setCrucialSj(-1);
01252         } else if (info->crucialSj()>=0) {
01253           // Just possible crucialSj still in but original out again
01254           int crucialSj=info->crucialSj();
01255           if (crucialSj>=numberXColumns+numberQuadraticRows) {
01256             if (sequenceOut_==crucialSj-numberXColumns-numberQuadraticRows)
01257               info->setCrucialSj(-1);
01258           } else {
01259             if (sequenceOut_-numberColumns_==crucialSj-numberXColumns)
01260               info->setCrucialSj(-1);
01261           }
01262         }
01263         if (info->crucialSj()<0)
01264           result=0;
01265         if (whatNext==1) {
01266           returnCode =-2; // refactorize
01267         } else if (whatNext==2) {
01268           // maximum iterations or equivalent
01269           returnCode=3;
01270         } else if(numberIterations_ == lastGoodIteration_
01271                   + 2 * factorization_->maximumPivots()) {
01272           // done a lot of flips - be safe
01273           returnCode =-2; // refactorize
01274         }
01275         // may need to go round again
01276         cleanupIteration = 1;
01277         // may not be correct on second time
01278         if (result&&(returnCode==-1||returnCode==-2||returnCode==-3)) {
01279           int crucialSj=info->crucialSj();
01280           if (sequenceOut_<numberXColumns) {
01281             chosen =sequenceOut_ + numberQuadraticRows + numberXColumns; // sj variable
01282           } else if (sequenceOut_>=numberColumns_) {
01283             // Does this mean we can change pi
01284             int iRow = sequenceOut_-numberColumns_;
01285             if (iRow<numberXRows) {
01286               chosen=iRow+numberXColumns;
01287             } else {
01288               printf("Row %d is in column part\n",iRow);
01289               abort();
01290             }
01291           } else if (sequenceOut_<numberQuadraticRows+numberXColumns) {
01292             // pi out
01293             chosen = sequenceOut_-numberXColumns+numberColumns_;
01294           } else {
01295             // sj out
01296             chosen = sequenceOut_-numberQuadraticRows-numberXColumns;
01297           }
01298           // But double check as original incoming might have gone out
01299           if (chosen==crucialSj) {
01300             chosen=-1;
01301             break; // means original has gone out
01302           }
01303           rowArray_[0]->clear();
01304           columnArray_[0]->clear();
01305           if (returnCode==-2) {
01306             // factorization
01307             nextSequenceIn = chosen;
01308             break;
01309           }
01310         } else {
01311           break;
01312         }
01313       }
01314       if (returnCode<-1&&returnCode>-5) {
01315         problemStatus_=-2; // 
01316       } else if (returnCode==-5) {
01317         // something flagged - continue;
01318       } else if (returnCode==2) {
01319         problemStatus_=-5; // looks unbounded
01320       } else if (returnCode==4) {
01321         problemStatus_=-2; // looks unbounded but has iterated
01322       } else if (returnCode!=-1) {
01323         assert(returnCode==3);
01324         problemStatus_=3;
01325       }
01326     } else {
01327       // no pivot column
01328 #ifdef CLP_DEBUG
01329       if (handler_->logLevel()&32)
01330         printf("** no column pivot\n");
01331 #endif
01332       if (nonLinearCost_->numberInfeasibilities())
01333         problemStatus_=-4; // might be infeasible 
01334       returnCode=0;
01335       break;
01336     }
01337   }
01338   info->setSequenceIn(nextSequenceIn);
01339   return returnCode;
01340 }
01341 /* 
01342    Row array has pivot column
01343    This chooses pivot row.
01344    For speed, we may need to go to a bucket approach when many
01345    variables go through bounds
01346    On exit rhsArray will have changes in costs of basic variables
01347 */
01348 int 
01349 ClpSimplexPrimalQuadratic::primalRow(CoinIndexedVector * rowArray,
01350                                      CoinIndexedVector * rhsArray,
01351                                      CoinIndexedVector * spareArray,
01352                                      CoinIndexedVector * spareArray2,
01353                                      ClpQuadraticInfo * info,
01354                                      int cleanupIteration)
01355 {
01356   int result=1;
01357   
01358   // sequence stays as row number until end
01359   pivotRow_=-1;
01360   int numberSwapped=0;
01361   int numberRemaining=0;
01362   int crucialSj = info->crucialSj();
01363   if (crucialSj<0)
01364     result=0; // linear
01365   int numberThru =0; // number gone thru a barrier
01366   int lastThru =0; // number gone thru a barrier on last time
01367   
01368   double totalThru=0.0; // for when variables flip
01369   double acceptablePivot=1.0e-7;
01370   if (factorization_->pivots())
01371     acceptablePivot=1.0e-5; // if we have iterated be more strict
01372   double bestEverPivot=acceptablePivot;
01373   int lastPivotRow = -1;
01374   double lastPivot=0.0;
01375   double lastTheta=1.0e50;
01376   int lastNumberSwapped=0;
01377 
01378   // use spareArrays to put ones looked at in
01379   // First one is list of candidates
01380   // We could compress if we really know we won't need any more
01381   // Second array has current set of pivot candidates
01382   // with a backup list saved in double * part of indexed vector
01383 
01384   // for zeroing out arrays after
01385   int maximumSwapped=0;
01386   // pivot elements
01387   double * spare;
01388   // indices
01389   int * index, * indexSwapped;
01390   int * saveSwapped;
01391   spareArray->clear();
01392   spareArray2->clear();
01393   spare = spareArray->denseVector();
01394   index = spareArray->getIndices();
01395   saveSwapped = (int *) spareArray2->denseVector();
01396   indexSwapped = spareArray2->getIndices();
01397 
01398   // we also need somewhere for effective rhs
01399   double * rhs=rhsArray->denseVector();
01400 
01401   /*
01402     First we get a list of possible pivots.  We can also see if the
01403     problem looks unbounded.
01404 
01405     At first we increase theta and see what happens.  We start
01406     theta at a reasonable guess.  If in right area then we do bit by bit.
01407     We save possible pivot candidates
01408 
01409    */
01410 
01411   // do first pass to get possibles 
01412   // We can also see if unbounded
01413 
01414   double * work=rowArray->denseVector();
01415   int number=rowArray->getNumElements();
01416   int * which=rowArray->getIndices();
01417 
01418   // we need to swap sign if coming in from ub
01419   double way = directionIn_;
01420   double maximumMovement;
01421   if (way>0.0) 
01422     maximumMovement = min(1.0e30,upperIn_-valueIn_);
01423   else
01424     maximumMovement = min(1.0e30,valueIn_-lowerIn_);
01425 
01426   int iIndex;
01427 
01428   // Work out coefficients for quadratic term
01429   // This is expanded one
01430   const CoinPackedMatrix * quadratic = info->quadraticObjective();
01431   const int * columnQuadratic = quadratic->getIndices();
01432   const int * columnQuadraticStart = quadratic->getVectorStarts();
01433   const int * columnQuadraticLength = quadratic->getVectorLengths();
01434   const double * quadraticElement = quadratic->getElements();
01435   //const double * originalCost = info->originalObjective();
01436   // Use rhsArray
01437   rhsArray->clear();
01438   int * index2 = rhsArray->getIndices();
01439   int numberXColumns = info->numberXColumns();
01440   int number2=0;
01441   //int numberOriginalRows = info->numberXRows();
01442   // sj 
01443   int iSjRow=-1;
01444   // sj for incoming 
01445   int iSjRow2=-1,crucialSj2=-1;
01446   if (sequenceIn_<numberXColumns) {
01447     crucialSj2 = sequenceIn_;
01448     crucialSj2 += numberRows_; // sj2 which should go to 0.0
01449   } else if (sequenceIn_>=numberColumns_) {
01450     int iRow=sequenceIn_-numberColumns_;
01451     crucialSj2 = iRow;
01452     crucialSj2 += numberXColumns; // sj2 which should go to 0.0
01453   }
01454   double tj = 0.0;
01455   // Change in objective will be theta*coeff1 + theta*theta*coeff2
01456   double coeff1 = 0.0;
01457   double coeff2 = 0.0;
01458   double coeffSlack=0.0;
01459   for (iIndex=0;iIndex<number;iIndex++) {
01460     int iRow = which[iIndex];
01461     double alpha = -work[iRow]*way;
01462     int iPivot=pivotVariable_[iRow];
01463     if (numberIterations_==17)
01464       printf("row %d col %d alpha %g solution %g\n",iRow,iPivot,alpha,solution_[iPivot]);
01465     if (iPivot<numberXColumns) {
01466       index2[number2++]=iPivot;
01467       rhs[iPivot]=alpha;
01468       coeff1 += alpha*cost_[iPivot];
01469       //printf("col %d alpha %g solution %g cost %g scale %g\n",iPivot,alpha,solution_[iPivot],
01470       //     cost_[iPivot],columnScale_[iPivot]);
01471     } else {
01472       if (iPivot>=numberColumns_) {
01473         // ? do we go through column of pi
01474         assert (iPivot!=crucialSj);
01475         coeffSlack += alpha*cost_[iPivot];
01476       } else if (iPivot<numberRows_) {
01477         // ? do we go through column of pi
01478         if (iPivot==crucialSj) {
01479           tj = alpha;
01480           iSjRow = iRow;
01481         }
01482       } else {
01483         if (iPivot==crucialSj) {
01484           tj = alpha;
01485           iSjRow = iRow;
01486         }
01487       }
01488     }
01489     if (iPivot==crucialSj2)
01490       iSjRow2=iRow;
01491   }
01492   // Incoming
01493   if (sequenceIn_<numberXColumns) {
01494     index2[number2++]=sequenceIn_;
01495     rhs[sequenceIn_]=way;
01496     //printf("incoming col %d alpha %g solution %g cost %g scale %g\n",sequenceIn_,way,valueIn_,
01497     //   cost_[sequenceIn_],columnScale_[sequenceIn_]);
01498     coeff1 += way*cost_[sequenceIn_];
01499   } else {
01500     //printf("incoming new col %d alpha %g solution %g\n",sequenceIn_,way,valueIn_);
01501     coeffSlack += way*cost_[sequenceIn_];
01502   }
01503   printf("coeff1 now %g\n",coeff1);
01504   rhsArray->setNumElements(number2);
01505   double largestCoeff1=1.0e-20;
01506   for (iIndex=0;iIndex<number2;iIndex++) {
01507     int iColumn=index2[iIndex];
01508     //double valueI = solution_[iColumn];
01509     double alphaI = rhs[iColumn];
01510     int j;
01511     for (j=columnQuadraticStart[iColumn];
01512          j<columnQuadraticStart[iColumn]+columnQuadraticLength[iColumn];j++) {
01513       int jColumn = columnQuadratic[j];
01514       double valueJ = solution_[jColumn];
01515       double alphaJ = rhs[jColumn];
01516       double elementValue = quadraticElement[j];
01517       double addValue = (valueJ*alphaI)*elementValue;
01518       largestCoeff1 = max(largestCoeff1,fabs(addValue));
01519       coeff1 += addValue;
01520       coeff2 += (alphaI*alphaJ)*elementValue;
01521     }
01522   }
01523   coeff2 *= 0.5;
01524   if (coeffSlack)
01525     printf("slack has non-zero cost - trouble?\n");
01526   coeff1 += coeffSlack;
01527   //coeff1 = way*dualIn_;
01528   int accuracyFlag=0;
01529   if (!cleanupIteration) {
01530     if (fabs(dualIn_)<dualTolerance_&&fabs(coeff1)<dualTolerance_) {
01531       dualIn_=0.0;
01532       coeff1=0.0;
01533     }
01534     if (fabs(way*coeff1-dualIn_)>1.0e-2*(1.0+fabs(dualIn_)))
01535       printf("primal error %g, largest %g, coeff1 %g, dualin %g\n",
01536              largestPrimalError_,largestCoeff1,way*coeff1,dualIn_);
01537     assert (fabs(way*coeff1-dualIn_)<1.0e-1*(1.0+fabs(dualIn_)));
01538     assert (way*coeff1*dualIn_>=0.0);
01539     if (way*coeff1*dualIn_<0.0) {
01540       // bad
01541       accuracyFlag=2;
01542     } else if (fabs(way*coeff1-dualIn_)>1.0e-3*(1.0+fabs(dualIn_))) {
01543       // not wonderful
01544       accuracyFlag=1;
01545     }
01546     if (crucialSj>=0) {
01547       solution_[crucialSj]=way*coeff1;
01548     }
01549   } else if (dualIn_<0.0&&way*coeff1>1.0e-2) {
01550     printf("bad pair\n");
01551     accuracyFlag=1;
01552   } else if (dualIn_>0.0&&way*coeff1<-1.0e-2) {
01553     accuracyFlag=1;
01554     printf("bad pair\n");
01555   }
01556   // interesting places are where derivative zero or sj goes to zero
01557   double d1,d2=1.0e50;
01558   if (fabs(coeff2)>1.0e-9)
01559     d1 = - 0.5*coeff1/coeff2;
01560   else if (coeff1<=1.0e-6)
01561     d1 = maximumMovement;
01562   else
01563     d1 = 0.0;
01564   if (fabs(tj)<1.0e-7||!cleanupIteration) {
01565     //if (sequenceIn_<numberXColumns)
01566       //printf("column %d is basically linear\n",sequenceIn_);
01567     //assert(!columnQuadraticLength[sequenceIn_]);
01568   } else {
01569     d2 = -solution_[crucialSj]/tj;
01570     if (d2<0.0) {
01571       printf("d2 would be negative at %g\n",d2);
01572       d2=1.0e50;
01573     }
01574   }
01575   if (d1>1.0e10&&d2>1.0e10) {
01576     // linear variable entering
01577     // maybe we should have done dual iteration to force sj to 0.0
01578     //printf("linear variable\n");
01579   }
01580   handler_->message(CLP_QUADRATIC_PRIMAL_DETAILS,messages_)
01581     <<coeff1<<coeff2<<coeffSlack<<dualIn_<<d1<<d2
01582     <<CoinMessageEol;
01583   // reality check
01584   {
01585     if (crucialSj2>=0) {
01586       // see if works out
01587       if (getColumnStatus(crucialSj2)==basic) {
01588         if (iSjRow2>=0) {
01589           //corresponding alpha nonzero
01590           double alpha=work[iSjRow2];
01591           printf("Sj alpha %g sol %g ratio %g\n",alpha,solution_[crucialSj2],solution_[crucialSj2]/alpha);
01592           if (fabs(fabs(d1)-fabs(solution_[crucialSj2]/alpha))>1.0e-3*(1.0+fabs(d1))) {
01593             printf("bad test\n");
01594             if (factorization_->pivots())
01595               accuracyFlag=2;
01596           }
01597           d1=fabs(solution_[crucialSj2]/alpha);
01598         } else {
01599           printf("Sj basic but no alpha\n");
01600         }
01601       } else {
01602         printf("Sj not basic\n");
01603       }
01604     }
01605   }
01606   //if (!cleanupIteration)
01607   //dualIn_ = way*coeff1;
01608   double mind1d2=1.0e50;
01609   if (cleanupIteration) {
01610     // we are only interested in d1 if smaller than d2
01611     mind1d2 = min(maximumMovement,d2);
01612     //if (d1>1.0e-8&&d1<0.999*d2)
01613     //mind1d2=d1;
01614   } else {
01615     // There is no d2 - d1 refers to crucialSj
01616     if (d1>1.0e-5) {
01617       mind1d2 = min(maximumMovement,d1);
01618       //assert (d1>=0.0);
01619     }
01620   }
01621   maximumMovement = min(maximumMovement,mind1d2);
01622   double trueMaximumMovement;
01623   if (way>0.0) 
01624     trueMaximumMovement = min(1.0e30,upperIn_-valueIn_);
01625   else
01626     trueMaximumMovement = min(1.0e30,valueIn_-lowerIn_);
01627   rhsArray->clear();
01628   double tentativeTheta = maximumMovement;
01629   double upperTheta = maximumMovement;
01630   bool throwAway=false;
01631   if (numberIterations_==1750) {
01632     printf("Bad iteration coming up after iteration %d\n",numberIterations_);
01633   }
01634 
01635   double minimumAny=1.0e50;
01636   int whichMinimum=-1;
01637   double minimumAlpha=0.0;
01638   for (iIndex=0;iIndex<number;iIndex++) {
01639 
01640     int iRow = which[iIndex];
01641     double alpha = work[iRow];
01642     int iPivot=pivotVariable_[iRow];
01643     alpha *= way;
01644     double oldValue = solution(iPivot);
01645     // get where in bound sequence
01646     if (alpha>0.0) {
01647       // basic variable going towards lower bound
01648       double bound = lower(iPivot);
01649       oldValue -= bound;
01650     } else if (alpha<0.0) {
01651       // basic variable going towards upper bound
01652       double bound = upper(iPivot);
01653       oldValue = bound-oldValue;
01654     }
01655     if (iPivot>=numberXColumns&&iPivot<numberColumns_) {
01656       double bound=0.0;
01657       double oldValue2 = solution(iPivot);
01658       if (alpha>0.0) {
01659         // basic variable going towards lower bound
01660         oldValue2 -= bound;
01661       } else if (alpha<0.0) {
01662         // basic variable going towards upper bound
01663         oldValue2 = bound-oldValue;
01664       }
01665       double value = oldValue2-minimumAny*fabs(alpha);
01666       if (value*oldValue2<0.0) {
01667         double ratio = fabs(oldValue2/alpha);
01668         if (ratio<minimumAny&&fabs(alpha)>1.0e2*acceptablePivot) {
01669           minimumAny = ratio;
01670           whichMinimum = iRow;
01671           minimumAlpha= fabs(alpha);
01672         }
01673       }
01674     }
01675     double value = oldValue-tentativeTheta*fabs(alpha);
01676     assert (oldValue>=-primalTolerance_*1.0001);
01677     if (value<-primalTolerance_) {
01678       // add to list
01679       spare[numberRemaining]=alpha;
01680       rhs[iRow]=oldValue;
01681       index[numberRemaining++]=iRow;
01682       double value=oldValue-upperTheta*fabs(alpha);
01683       if (value<-primalTolerance_&&fabs(alpha)>=acceptablePivot)
01684         upperTheta = (oldValue+primalTolerance_)/fabs(alpha);
01685     }
01686   }
01687 
01688   // we need to keep where rhs non-zeros are
01689   int numberInRhs=numberRemaining;
01690   memcpy(rhsArray->getIndices(),index,numberInRhs*sizeof(int));
01691   rhsArray->setNumElements(numberInRhs);
01692 
01693   theta_=maximumMovement;
01694 
01695   bool goBackOne = false;
01696   double fake=1.0e-2;
01697 
01698   if (numberRemaining) {
01699 
01700     // looks like pivoting
01701     // now try until reasonable theta
01702     tentativeTheta = max(10.0*upperTheta,1.0e-7);
01703     tentativeTheta = min(tentativeTheta,maximumMovement);
01704     
01705     // loops increasing tentative theta until can't go through
01706     
01707     while (tentativeTheta <= maximumMovement) {
01708       double bestPivotBeforeInteresting=0.0;
01709       double thruThis = 0.0;
01710       
01711       double bestPivot=acceptablePivot;
01712       pivotRow_ = -1;
01713       
01714       numberSwapped = 0;
01715       
01716       upperTheta = maximumMovement;
01717       
01718       for (iIndex=0;iIndex<numberRemaining;iIndex++) {
01719 
01720         int iRow = index[iIndex];
01721         double alpha = spare[iIndex];
01722         double oldValue = rhs[iRow];
01723         double value = oldValue-tentativeTheta*fabs(alpha);
01724 
01725         if (value<-primalTolerance_) {
01726           // how much would it cost to go thru
01727           thruThis += alpha*
01728             nonLinearCost_->changeInCost(pivotVariable_[iRow],alpha);
01729           // goes on swapped list (also means candidates if too many)
01730           indexSwapped[numberSwapped++]=iRow;
01731           if (fabs(alpha)>bestPivot) {
01732             bestPivot=fabs(alpha);
01733             pivotRow_ = iRow;
01734             theta_ = oldValue/bestPivot;
01735           }
01736         } else {
01737           value = oldValue-upperTheta*fabs(alpha);
01738           if (value<-primalTolerance_ && fabs(alpha)>=acceptablePivot) 
01739             upperTheta = (oldValue+primalTolerance_)/fabs(alpha);
01740         }
01741       }
01742       
01743       maximumSwapped = max(maximumSwapped,numberSwapped);
01744       bestPivotBeforeInteresting=bestPivot;
01745 
01746       //double dualCheck = - 2.0*coeff2*tentativeTheta - coeff1 - 0.1*infeasibilityCost_;
01747       double dualCheck = - 2.0*coeff2*tentativeTheta - coeff1;
01748       // but make a bit more pessimistic if pivot
01749       //if (bestPivot>acceptablePivot)
01750       //dualCheck=max(dualCheck-100.0*dualTolerance_,0.99*dualCheck);
01751       //dualCheck=0.0;
01752       if ((totalThru+thruThis>=dualCheck&&bestPivot>acceptablePivot)||fake*bestPivot>1.0e-3) {
01753         // We should be pivoting in this batch
01754         // so compress down to this lot
01755 
01756         int saveNumber = numberRemaining;
01757         numberRemaining=0;
01758         for (iIndex=0;iIndex<numberSwapped;iIndex++) {
01759           int iRow = indexSwapped[iIndex];
01760           spare[numberRemaining]=way*work[iRow];
01761           index[numberRemaining++]=iRow;
01762         }
01763         memset(spare+numberRemaining,0,
01764                (saveNumber-numberRemaining)*sizeof(double));
01765         double lastThru = totalThru;
01766         int iTry;
01767 #define MAXTRY 100
01768         // first get ratio with tolerance
01769         for (iTry=0;iTry<MAXTRY;iTry++) {
01770           
01771           upperTheta=maximumMovement;
01772           numberSwapped = 0;
01773           
01774           for (iIndex=0;iIndex<numberRemaining;iIndex++) {
01775             
01776             int iRow = index[iIndex];
01777             double alpha = fabs(spare[iIndex]);
01778             double oldValue = rhs[iRow];
01779             double value = oldValue-upperTheta*alpha;
01780             
01781             if (value<-primalTolerance_ && alpha>=acceptablePivot) 
01782               upperTheta = (oldValue+primalTolerance_)/alpha;
01783             
01784           }
01785           
01786           // now look at best in this lot
01787           bestPivot=acceptablePivot;
01788           pivotRow_=-1;
01789           for (iIndex=0;iIndex<numberRemaining;iIndex++) {
01790             
01791             int iRow = index[iIndex];
01792             double alpha = spare[iIndex];
01793             double oldValue = rhs[iRow];
01794             double value = oldValue-upperTheta*fabs(alpha);
01795             
01796             if (value<=0) {
01797               // how much would it cost to go thru
01798               totalThru += alpha*
01799                 nonLinearCost_->changeInCost(pivotVariable_[iRow],alpha);
01800               // goes on swapped list (also means candidates if too many)
01801               indexSwapped[numberSwapped++]=iRow;
01802               if (fabs(alpha)>bestPivot) {
01803                 bestPivot=fabs(alpha);
01804                 theta_ = oldValue/bestPivot;
01805                 pivotRow_=iRow;
01806               }
01807             } else {
01808               value = oldValue-upperTheta*fabs(alpha);
01809               if (value<-primalTolerance_ && fabs(alpha)>=acceptablePivot) 
01810                 upperTheta = (oldValue+primalTolerance_)/fabs(alpha);
01811             }
01812           }
01813           
01814           maximumSwapped = max(maximumSwapped,numberSwapped);
01815           if (bestPivot<0.1*bestEverPivot&&
01816               bestEverPivot>1.0e-6&&bestPivot<1.0e-3) {
01817             // back to previous one
01818             goBackOne = true;
01819             break;
01820           } else if (pivotRow_==-1&&upperTheta>largeValue_) {
01821             if (lastPivot>acceptablePivot) {
01822               // back to previous one
01823               goBackOne = true;
01824               //break;
01825             } else {
01826               // can only get here if all pivots so far too small
01827             }
01828             break;
01829           } else {
01830             dualCheck = - 2.0*coeff2*theta_ - coeff1;
01831             if (bestPivotBeforeInteresting>1.0e-4&&bestPivot<1.0e-6)
01832               dualCheck=1.0e7;
01833             if ((totalThru>=dualCheck||fake*bestPivot>1.0e-3)
01834                 &&(sequenceIn_<numberXColumns||sequenceIn_>=numberColumns_)) {
01835               if (!cleanupIteration) {
01836                 // We can pivot out sj
01837                 if (upperTheta==maximumMovement) {
01838                   printf("figures\n");
01839                 } else if (iSjRow2>=0) {
01840                   if (lastThru>=dualCheck&&theta_<trueMaximumMovement) {
01841                     printf("totalThru %g, lastThru %g - taking sj to zero?\n",totalThru,lastThru);
01842                     // make sure will take correct path
01843                     mind1d2=1.0;
01844                     maximumMovement=1.0;
01845                     d2=0.0;
01846                     pivotRow_=-1;
01847                   }
01848                 }
01849               } else {
01850                 if (pivotRow_<0&&lastPivotRow<0)
01851                   throwAway=true;
01852               }
01853               break; // no point trying another loop
01854             } else if (totalThru>=dualCheck||fake*bestPivot>1.0e-3||upperTheta==maximumMovement) {
01855               break; // no point trying another loop
01856             } else {
01857               // skip this lot
01858               nonLinearCost_->goThru(numberSwapped,way,indexSwapped, work,rhs);
01859               lastPivotRow=pivotRow_;
01860               lastTheta = theta_;
01861               lastThru = numberThru;
01862               numberThru += numberSwapped;
01863               lastNumberSwapped = numberSwapped;
01864               memcpy(saveSwapped,indexSwapped,lastNumberSwapped*sizeof(int));
01865               if (bestPivot>bestEverPivot)
01866                 bestEverPivot=bestPivot;
01867               lastThru = totalThru;
01868             }
01869           }
01870         }
01871         break;
01872       } else {
01873         // skip this lot
01874         nonLinearCost_->goThru(numberSwapped,way,indexSwapped, work,rhs);
01875         lastPivotRow=pivotRow_;
01876         lastTheta = theta_;
01877         lastThru = numberThru;
01878         numberThru += numberSwapped;
01879         lastNumberSwapped = numberSwapped;
01880         memcpy(saveSwapped,indexSwapped,lastNumberSwapped*sizeof(int));
01881         if (bestPivot>bestEverPivot)
01882           bestEverPivot=bestPivot;
01883         totalThru += thruThis;
01884         tentativeTheta = 2.0*upperTheta;
01885       }
01886     }
01887     // can get here without pivotRow_ set but with lastPivotRow
01888     if (goBackOne||(pivotRow_<0&&lastPivotRow>=0)) {
01889       // back to previous one
01890       pivotRow_=lastPivotRow;
01891       theta_ = lastTheta;
01892             // undo this lot
01893       nonLinearCost_->goBack(lastNumberSwapped,saveSwapped,rhs);
01894       memcpy(indexSwapped,saveSwapped,lastNumberSwapped*sizeof(int));
01895       numberSwapped = lastNumberSwapped;
01896     }
01897   }
01898   if (0&&minimumAny<theta_&&cleanupIteration&&bestEverPivot<1.0e-2
01899       &&minimumAlpha>bestEverPivot*1.0e2&&minimumAny>1.0e-1&&info->currentPhase()==0) {
01900     printf("Possible other pivot %d %g %g - alpha %g\n",
01901            whichMinimum,minimumAny,theta_,minimumAlpha);
01902     pivotRow_ = whichMinimum;
01903     alpha_ = work[pivotRow_];
01904     // translate to sequence
01905     sequenceOut_ = pivotVariable_[pivotRow_];
01906     valueOut_ = solution(sequenceOut_);
01907     lowerOut_=0.0;
01908     upperOut_=0.0;
01909     theta_= fabs(valueOut_/alpha_);
01910 
01911     if (way<0.0) 
01912       theta_ = - theta_;
01913     if (alpha_*way<0.0) {
01914       directionOut_=-1;      // to upper bound
01915     } else {
01916       directionOut_=1;      // to lower bound
01917     }
01918     dualOut_ = reducedCost(sequenceOut_);
01919   } else {
01920 
01921   if (pivotRow_>=0) {
01922     if (0) {
01923       double move = coeff1*theta_+coeff2*theta_*theta_;
01924       printf("Predicted change in obj is %g %g %g\n",
01925              move,objectiveValue_-move,objectiveValue_+move);
01926     }
01927 #define MINIMUMTHETA 1.0e-12
01928     // will we need to increase tolerance
01929 #ifdef CLP_DEBUG
01930     bool found=false;
01931 #endif
01932     double largestInfeasibility = primalTolerance_;
01933     if (theta_<MINIMUMTHETA) {
01934       theta_=MINIMUMTHETA;
01935       for (iIndex=0;iIndex<numberSwapped;iIndex++) {
01936         int iRow = indexSwapped[iIndex];
01937 #ifdef CLP_DEBUG
01938         if (iRow==pivotRow_)
01939           found=true;
01940 #endif
01941         largestInfeasibility = max (largestInfeasibility,
01942                                     -(rhs[iRow]-fabs(work[iRow])*theta_));
01943       }
01944 #ifdef CLP_DEBUG
01945       assert(found);
01946       if (largestInfeasibility>primalTolerance_&&(handler_->logLevel()&32))
01947         printf("Primal tolerance increased from %g to %g\n",
01948                primalTolerance_,largestInfeasibility);
01949 #endif
01950       primalTolerance_ = max(primalTolerance_,largestInfeasibility);
01951     }
01952     alpha_ = work[pivotRow_];
01953     // translate to sequence
01954     sequenceOut_ = pivotVariable_[pivotRow_];
01955     valueOut_ = solution(sequenceOut_);
01956     lowerOut_=lower_[sequenceOut_];
01957     upperOut_=upper_[sequenceOut_];
01958 
01959     if (way<0.0) 
01960       theta_ = - theta_;
01961     double newValue = valueOut_ - theta_*alpha_;
01962     if (alpha_*way<0.0) {
01963       directionOut_=-1;      // to upper bound
01964       if (fabs(theta_)>1.0e-6)
01965         upperOut_ = nonLinearCost_->nearest(sequenceOut_,newValue);
01966       else
01967         upperOut_ = newValue;
01968     } else {
01969       directionOut_=1;      // to lower bound
01970       if (fabs(theta_)>1.0e-6)
01971         lowerOut_ = nonLinearCost_->nearest(sequenceOut_,newValue);
01972       else
01973         lowerOut_ = newValue;
01974     }
01975     dualOut_ = reducedCost(sequenceOut_);
01976   } else {
01977     // If no pivot but bad move then throw away
01978     if (throwAway&&(sequenceIn_<numberXColumns||sequenceIn_>=numberColumns_)) {
01979       assert (pivotRow_<0);
01980       accuracyFlag=2;
01981     }
01982     if (maximumMovement<1.0e20&&maximumMovement==trueMaximumMovement) {
01983       // flip
01984       theta_ = maximumMovement;
01985       pivotRow_ = -2; // so we can tell its a flip
01986       result=0;
01987       sequenceOut_ = sequenceIn_;
01988       valueOut_ = valueIn_;
01989       dualOut_ = dualIn_;
01990       lowerOut_ = lowerIn_;
01991       upperOut_ = upperIn_;
01992       alpha_ = 0.0;
01993       if (accuracyFlag<2)
01994         accuracyFlag=0;
01995       if (way<0.0) {
01996         directionOut_=1;      // to lower bound
01997         theta_ = lowerOut_ - valueOut_;
01998       } else {
01999         directionOut_=-1;      // to upper bound
02000         theta_ = upperOut_ - valueOut_;
02001       }
02002       // we may still have sj to get rid of
02003     } else if (fabs(maximumMovement-mind1d2)<dualTolerance_) {
02004       // crucialSj local copy i.e. dj going to zero
02005       if (maximumMovement==d2) {
02006         // sj going to zero
02007         result=0;
02008       } else {
02009         // incoming dj going to zero
02010         if (!cleanupIteration) {
02011           result=0;
02012           iSjRow=iSjRow2;
02013           if (iSjRow>=0)
02014             crucialSj = pivotVariable_[iSjRow];
02015           else
02016             crucialSj=-1;
02017           assert (pivotRow_<0);
02018           // If crucialSj <0 then make superbasic?
02019           if (crucialSj<0) {
02020             printf("**ouch\n");
02021             theta_ = maximumMovement;
02022             pivotRow_ = -2; // so we can tell its a flip
02023             result=0;
02024             sequenceOut_ = sequenceIn_;
02025             valueOut_ = valueIn_;
02026             dualOut_ = dualIn_;
02027             lowerOut_ = lowerIn_;
02028             upperOut_ = upperIn_;
02029             alpha_ = 0.0;
02030             if (accuracyFlag<2)
02031               accuracyFlag=0;
02032             if (way<0.0) {
02033               directionOut_=1;      // to lower bound
02034               lowerIn_ = valueOut_-theta_;
02035               theta_ = lowerIn_ - valueOut_;
02036             } else {
02037               directionOut_=-1;      // to upper bound
02038               upperIn_ = valueOut_+theta_;
02039               theta_ = upperIn_ - valueOut_;
02040             }
02041           }
02042         } else {
02043           assert (fabs(dualIn_)<1.0e-3);
02044           result=1;
02045           if (minimumAlpha>0.0) {
02046             // could do this in other places if pivot looks good
02047             printf("Should take minimum\n");
02048             pivotRow_ = whichMinimum;
02049             alpha_ = work[pivotRow_];
02050             // translate to sequence
02051             sequenceOut_ = pivotVariable_[pivotRow_];
02052             valueOut_ = solution(sequenceOut_);
02053             theta_ = minimumAny;
02054             if (way<0.0) 
02055               theta_ = - theta_;
02056             lowerOut_=0.0;
02057             upperOut_=0.0;
02058             //????
02059             dualOut_ = reducedCost(sequenceOut_);
02060           }
02061         }
02062       }
02063       if (!result&&crucialSj>=0) {
02064         setColumnStatus(crucialSj,isFree);
02065         pivotRow_ = iSjRow;
02066         alpha_ = work[pivotRow_];
02067         // translate to sequence
02068         sequenceOut_ = pivotVariable_[pivotRow_];
02069         assert (sequenceOut_==crucialSj);
02070         valueOut_ = solution(sequenceOut_);
02071         theta_ = fabs(valueOut_/alpha_);
02072         if (fabs(maximumMovement-theta_)>1.0e-3*(1.0+maximumMovement))
02073           printf("maximumMovement %g mismatch with theta %g\n",maximumMovement,theta_);;
02074         if (way<0.0) 
02075           theta_ = - theta_;
02076         lowerOut_=0.0;
02077         upperOut_=0.0;
02078         //????
02079         dualOut_ = reducedCost(sequenceOut_);
02080       }
02081     } else {
02082       // need to do something
02083       accuracyFlag=2;
02084     }
02085   }
02086   }
02087 
02088 
02089   // clear arrays
02090 
02091   memset(spare,0,numberRemaining*sizeof(double));
02092   memset(saveSwapped,0,maximumSwapped*sizeof(int));
02093 
02094   // put back original bounds etc
02095   nonLinearCost_->goBackAll(rhsArray);
02096 
02097   rhsArray->clear();
02098   // Change in objective will be theta*coeff1 + theta*theta*coeff2
02099   objectiveValue_ += theta_*coeff1+theta_*theta_*coeff2;
02100   {
02101     int iColumn;
02102     objectiveValue_ =0.0;
02103     CoinPackedMatrix * quadratic = 
02104       info->originalObjective()->quadraticObjective();
02105     const int * columnQuadratic = quadratic->getIndices();
02106     const int * columnQuadraticStart = quadratic->getVectorStarts();
02107     const int * columnQuadraticLength = quadratic->getVectorLengths();
02108     const double * quadraticElement = quadratic->getElements();
02109     int numberColumns = info->numberXColumns();
02110     const double * objective = info->linearObjective();
02111     for (iColumn=0;iColumn<numberColumns;iColumn++) 
02112       objectiveValue_ += objective[iColumn]*solution_[iColumn];
02113     for (iColumn=0;iColumn<numberColumns;iColumn++) {
02114       double valueI = solution_[iColumn];
02115       int j;
02116       for (j=columnQuadraticStart[iColumn];
02117            j<columnQuadraticStart[iColumn]+columnQuadraticLength[iColumn];j++) {
02118         int jColumn = columnQuadratic[j];
02119         double valueJ = solution_[jColumn];
02120         double elementValue = quadraticElement[j];
02121         objectiveValue_ += 0.5*valueI*valueJ*elementValue;
02122       }
02123     }
02124   }
02125   if (accuracyFlag<2) {
02126     return result+10*accuracyFlag;
02127   } else {
02128     pivotRow_=1; // make sure correct path
02129     return 20;
02130   }
02131 }
02132 /* Checks if finished.  Updates status */
02133 void 
02134 ClpSimplexPrimalQuadratic::statusOfProblemInPrimal(int & lastCleaned,int type,
02135                                           ClpSimplexProgress * progress,
02136                                                    ClpQuadraticInfo * info)
02137 {
02138   if (info->currentPhase())
02139     info->setCurrentSolution(solution_);
02140   //info->saveStatus();
02141   
02142   if (type==2) {
02143     // trouble - restore solution
02144     memcpy(status_ ,saveStatus_,(numberColumns_+numberRows_)*sizeof(char));
02145     memcpy(rowActivityWork_,savedSolution_+numberColumns_ ,
02146            numberRows_*sizeof(double));
02147     memcpy(columnActivityWork_,savedSolution_ ,
02148            numberColumns_*sizeof(double));
02149     forceFactorization_=1; // a bit drastic but ..
02150     pivotRow_=-1; // say no weights update
02151     changeMade_++; // say change made
02152     info->restoreStatus();
02153   }
02154   int saveThreshold = factorization_->sparseThreshold();
02155   int tentativeStatus = problemStatus_;
02156   if (problemStatus_>-3||problemStatus_==-4) {
02157     // factorize
02158     // later on we will need to recover from singularities
02159     // also we could skip if first time
02160     // do weights
02161     // This may save pivotRow_ for use 
02162     primalColumnPivot_->saveWeights(this,1);
02163 
02164     if (type) {
02165       // is factorization okay?
02166       int numberPivots = factorization_->pivots();
02167       if (internalFactorize(1)) {
02168         if (solveType_==2) {
02169           // say odd
02170           problemStatus_=5;
02171           return;
02172         }
02173         numberIterations_ = progress_->lastIterationNumber(0);
02174         // no - restore previous basis
02175         assert (info->crucialSj()<0); // need to work out how to unwind
02176         assert (type==1);
02177         memcpy(status_ ,saveStatus_,(numberColumns_+numberRows_)*sizeof(char));
02178         memcpy(rowActivityWork_,savedSolution_+numberColumns_ ,
02179                numberRows_*sizeof(double));
02180         memcpy(columnActivityWork_,savedSolution_ ,
02181                numberColumns_*sizeof(double));
02182         forceFactorization_=1; // a bit drastic but ..
02183         type = 2;
02184         assert (internalFactorize(1)==0);
02185         info->restoreStatus();
02186         // flag incoming
02187         if (numberPivots==1) {
02188           int crucialSj = info->crucialSj();
02189           if (crucialSj<0) {
02190             setFlagged(sequenceIn_);
02191           } else {
02192             int iSequence;
02193             int numberXColumns = info->numberXColumns();
02194             if (crucialSj<numberRows_) {
02195               // row
02196               iSequence = crucialSj-numberXColumns+numberColumns_;
02197             } else {
02198               // column
02199               iSequence = crucialSj-numberRows_;
02200             }
02201             if (getColumnStatus(iSequence)!=basic) {
02202               setFlagged(iSequence);
02203               info->setSequenceIn(-1);
02204             } else {
02205               printf("**** %d is basic ?\n",iSequence);
02206             }
02207           }
02208         }
02209         changeMade_++; // say change made
02210       }
02211     }
02212     if (problemStatus_!=-4)
02213       problemStatus_=-3;
02214   }
02215   if (info->crucialSj()<0) {
02216     // at this stage status is -3 or -5 if looks unbounded
02217     // get primal and dual solutions
02218     // put back original costs and then check
02219     createRim(4);
02220     if (info->currentPhase()) {
02221       memcpy(solution_,info->currentSolution(),
02222              (numberRows_+numberColumns_)*sizeof(double));
02223     }
02224     gutsOfSolution(NULL,NULL);
02225     if (info->currentPhase()) {
02226       memcpy(solution_,info->currentSolution(),
02227              (numberRows_+numberColumns_)*sizeof(double));
02228       nonLinearCost_->checkInfeasibilities(primalTolerance_);
02229     }
02230     checkComplementarity(info,rowArray_[2],rowArray_[3]);
02231     // Double check reduced costs if no action
02232     if (progress->lastIterationNumber(0)==numberIterations_) {
02233       if (primalColumnPivot_->looksOptimal()) {
02234         numberDualInfeasibilities_ = 0;
02235         sumDualInfeasibilities_ = 0.0;
02236       }
02237     }
02238     // Check if looping
02239     int loop;
02240     if (type!=2) 
02241       loop = progress->looping(); // saves iteration number
02242     else
02243       loop=-1;
02244     //loop=-1;
02245     if (loop>=0) {
02246       problemStatus_ = loop; //exit if in loop
02247       return ;
02248     } else if (loop<-1) {
02249       // something may have changed
02250       gutsOfSolution(NULL,NULL);
02251       checkComplementarity(info,rowArray_[2],rowArray_[3]);
02252     }
02253     // really for free variables in
02254     //if((progressFlag_&2)!=0)
02255     //problemStatus_=-1;;
02256     progressFlag_ = 0; //reset progress flag
02257     
02258     handler_->message(CLP_SIMPLEX_STATUS,messages_)
02259       <<numberIterations_<<objectiveValue();
02260     handler_->printing(sumPrimalInfeasibilities_>0.0)
02261       <<sumPrimalInfeasibilities_<<numberPrimalInfeasibilities_;
02262     handler_->printing(sumDualInfeasibilities_>0.0)
02263       <<sumDualInfeasibilities_<<numberDualInfeasibilities_;
02264     handler_->printing(numberDualInfeasibilitiesWithoutFree_
02265                        <numberDualInfeasibilities_)
02266                          <<numberDualInfeasibilitiesWithoutFree_;
02267     handler_->message()<<CoinMessageEol;
02268     assert (primalFeasible());
02269     // we may wish to say it is optimal even if infeasible
02270     bool alwaysOptimal = (specialOptions_&1)!=0;
02271     // give code benefit of doubt
02272     if (sumOfRelaxedDualInfeasibilities_ == 0.0&&
02273         sumOfRelaxedPrimalInfeasibilities_ == 0.0&&info->sequenceIn()<0) {
02274       // say optimal (with these bounds etc)
02275       numberDualInfeasibilities_ = 0;
02276       sumDualInfeasibilities_ = 0.0;
02277       numberPrimalInfeasibilities_ = 0;
02278       sumPrimalInfeasibilities_ = 0.0;
02279     }
02280     // had ||(type==3&&problemStatus_!=-5) -- ??? why ????
02281     if (dualFeasible()||problemStatus_==-4) {
02282       if (nonLinearCost_->numberInfeasibilities()&&!alwaysOptimal) {
02283         //may need infeasiblity cost changed
02284         // we can see if we can construct a ray
02285         // make up a new objective
02286         double saveWeight = infeasibilityCost_;
02287         // save nonlinear cost as we are going to switch off costs
02288         ClpNonLinearCost * nonLinear = nonLinearCost_;
02289         // do twice to make sure Primal solution has settled
02290         // put non-basics to bounds in case tolerance moved
02291         // put back original costs
02292         createRim(4);
02293         // put all non-basic variables to bounds
02294         int iSequence;
02295         for (iSequence=0;iSequence<numberRows_+numberColumns_;iSequence++) {
02296           Status status = getStatus(iSequence);
02297           if (status==atLowerBound||status==isFixed)
02298             solution_[iSequence]=lower_[iSequence];
02299           else if (status==atUpperBound)
02300             solution_[iSequence]=upper_[iSequence];
02301         }
02302         nonLinearCost_->checkInfeasibilities(primalTolerance_);
02303         gutsOfSolution(NULL,NULL);
02304         nonLinearCost_->checkInfeasibilities(primalTolerance_);
02305         checkComplementarity(info,rowArray_[2],rowArray_[3]);
02306         
02307         infeasibilityCost_=1.0e100;
02308         // put back original costs
02309         createRim(4);
02310         nonLinearCost_->checkInfeasibilities(primalTolerance_);
02311         // may have fixed infeasibilities - double check
02312         if (nonLinearCost_->numberInfeasibilities()==0) {
02313           // carry on
02314           problemStatus_ = -1;
02315           infeasibilityCost_=saveWeight;
02316           nonLinearCost_->checkInfeasibilities(primalTolerance_);
02317           checkComplementarity(info,rowArray_[2],rowArray_[3]);
02318         } else {
02319           nonLinearCost_=NULL;
02320           // scale
02321           int i;
02322           for (i=0;i<numberRows_+numberColumns_;i++) 
02323             cost_[i] *= 1.0e-100;
02324           gutsOfSolution(NULL,NULL);
02325           nonLinearCost_=nonLinear;
02326           infeasibilityCost_=saveWeight;
02327           if ((infeasibilityCost_>=1.0e18||
02328                numberDualInfeasibilities_==0)&&perturbation_==101) {
02329             unPerturb(); // stop any further perturbation
02330             numberDualInfeasibilities_=1; // carry on
02331           }
02332           if (infeasibilityCost_>=1.0e20||
02333               numberDualInfeasibilities_==0) {
02334             // we are infeasible - use as ray
02335             delete [] ray_;
02336             ray_ = new double [numberRows_];
02337             memcpy(ray_,dual_,numberRows_*sizeof(double));
02338             // and get feasible duals
02339             infeasibilityCost_=0.0;
02340             createRim(4);
02341             // put all non-basic variables to bounds
02342             int iSequence;
02343             for (iSequence=0;iSequence<numberRows_+numberColumns_;iSequence++) {
02344               Status status = getStatus(iSequence);
02345               if (status==atLowerBound||status==isFixed)
02346                 solution_[iSequence]=lower_[iSequence];
02347               else if (status==atUpperBound)
02348                 solution_[iSequence]=upper_[iSequence];
02349             }
02350             nonLinearCost_->checkInfeasibilities(primalTolerance_);
02351             gutsOfSolution(NULL,NULL);
02352             checkComplementarity(info,rowArray_[2],rowArray_[3]);
02353             // so will exit
02354             infeasibilityCost_=1.0e30;
02355             // reset infeasibilities
02356             sumPrimalInfeasibilities_=nonLinearCost_->sumInfeasibilities();;
02357             numberPrimalInfeasibilities_=
02358               nonLinearCost_->numberInfeasibilities();
02359           }
02360           if (infeasibilityCost_<1.0e20) {
02361             infeasibilityCost_ *= 5.0;
02362             changeMade_++; // say change made
02363             handler_->message(CLP_PRIMAL_WEIGHT,messages_)
02364               <<infeasibilityCost_
02365               <<CoinMessageEol;
02366             // put back original costs and then check
02367             createRim(4);
02368             nonLinearCost_->checkInfeasibilities(0.0);
02369             gutsOfSolution(NULL,NULL);
02370             checkComplementarity(info,rowArray_[2],rowArray_[3]);
02371             problemStatus_=-1; //continue
02372           } else {
02373             // say infeasible
02374             problemStatus_ = 1;
02375           }
02376         }
02377       } else {
02378         // may be optimal
02379         if (perturbation_==101) {
02380           unPerturb(); // stop any further perturbation
02381           lastCleaned=-1; // carry on
02382         }
02383         if ( lastCleaned!=numberIterations_||unflag()) {
02384           handler_->message(CLP_PRIMAL_OPTIMAL,messages_)
02385             <<primalTolerance_
02386             <<CoinMessageEol;
02387           if (numberTimesOptimal_<4) {
02388             numberTimesOptimal_++;
02389             changeMade_++; // say change made
02390             if (numberTimesOptimal_==1) {
02391               // better to have small tolerance even if slower
02392               factorization_->zeroTolerance(1.0e-15);
02393             }
02394             lastCleaned=numberIterations_;
02395             if (primalTolerance_!=dblParam_[ClpPrimalTolerance])
02396               handler_->message(CLP_PRIMAL_ORIGINAL,messages_)
02397                 <<CoinMessageEol;
02398             double oldTolerance = primalTolerance_;
02399             primalTolerance_=dblParam_[ClpPrimalTolerance];
02400             // put back original costs and then check
02401             createRim(4);
02402             // put all non-basic variables to bounds
02403             int iSequence;
02404             for (iSequence=0;iSequence<numberRows_+numberColumns_;iSequence++) {
02405               Status status = getStatus(iSequence);
02406               if (status==atLowerBound||status==isFixed)
02407                 solution_[iSequence]=lower_[iSequence];
02408               else if (status==atUpperBound)
02409                 solution_[iSequence]=upper_[iSequence];
02410             }
02411             nonLinearCost_->checkInfeasibilities(oldTolerance);
02412             gutsOfSolution(NULL,NULL);
02413             checkComplementarity(info,rowArray_[2],rowArray_[3]);
02414             problemStatus_ = -1;
02415           } else {
02416             problemStatus_=0; // optimal
02417             if (lastCleaned<numberIterations_) {
02418               handler_->message(CLP_SIMPLEX_GIVINGUP,messages_)
02419                 <<CoinMessageEol;
02420             }
02421           }
02422         } else {
02423           problemStatus_=0; // optimal
02424         }
02425       }
02426     } else {
02427       // see if looks unbounded
02428       if (problemStatus_==-5) {
02429         if (nonLinearCost_->numberInfeasibilities()) {
02430           if (infeasibilityCost_>1.0e18&&perturbation_==101) {
02431             // back off weight
02432             infeasibilityCost_ = 1.0e13;
02433             unPerturb(); // stop any further perturbation
02434           }
02435           //we need infeasiblity cost changed
02436           if (infeasibilityCost_<1.0e20) {
02437             infeasibilityCost_ *= 5.0;
02438             changeMade_++; // say change made
02439             handler_->message(CLP_PRIMAL_WEIGHT,messages_)
02440               <<infeasibilityCost_
02441               <<CoinMessageEol;
02442             // put back original costs and then check
02443             createRim(4);
02444             gutsOfSolution(NULL,NULL);
02445             checkComplementarity(info,rowArray_[2],rowArray_[3]);
02446             problemStatus_=-1; //continue
02447           } else {
02448             // say unbounded
02449             problemStatus_ = 2;
02450           }
02451         } else {
02452           // say unbounded
02453           problemStatus_ = 2;
02454         } 
02455       } else {
02456         if(type==3&&problemStatus_!=-5)
02457           unflag(); // odd
02458         // carry on
02459         problemStatus_ = -1;
02460       }
02461     }
02462   } else {
02463     // don't update solution
02464     problemStatus_=-1;
02465   }
02466   if (type==0||type==1) {
02467     if (type!=1||!saveStatus_) {
02468       // create save arrays
02469       delete [] saveStatus_;
02470       delete [] savedSolution_;
02471       saveStatus_ = new unsigned char [numberRows_+numberColumns_];
02472       savedSolution_ = new double [numberRows_+numberColumns_];
02473     }
02474     // save arrays
02475     memcpy(saveStatus_,status_,(numberColumns_+numberRows_)*sizeof(char));
02476     memcpy(savedSolution_+numberColumns_ ,rowActivityWork_,
02477            numberRows_*sizeof(double));
02478     memcpy(savedSolution_ ,columnActivityWork_,numberColumns_*sizeof(double));
02479     info->saveStatus();
02480   }
02481   // restore weights (if saved) - also recompute infeasibility list
02482   if (tentativeStatus>-3) 
02483     primalColumnPivot_->saveWeights(this,(type <2) ? 2 : 4);
02484   else
02485     primalColumnPivot_->saveWeights(this,3);
02486   if (problemStatus_<0&&!changeMade_) {
02487     problemStatus_=4; // unknown
02488   }
02489   if (saveThreshold) {
02490     // use default at present
02491     factorization_->sparseThreshold(0);
02492     factorization_->goSparse();
02493   }
02494   lastGoodIteration_ = numberIterations_;
02495 }
02496 // Fills in reduced costs
02497 void 
02498 ClpSimplexPrimalQuadratic::createDjs (ClpQuadraticInfo * info,
02499                             CoinIndexedVector * array1, CoinIndexedVector * array2)
02500 {
02501   int numberQuadraticRows = info->numberQuadraticRows();
02502   int numberQuadraticColumns = info->numberQuadraticColumns();
02503   int numberXColumns = info->numberXColumns();
02504   int numberXRows = info->numberXRows();
02505   // Actually only need to do this after invert (use extra parameter to createDjs)
02506   // or when infeasibilities change
02507   // recode to do this later and update rather than recompute
02508   // When it is "change" then we don't need b (original rhs)
02509   {
02510     // update costs
02511     double * storedCost = lower_+numberColumns_+numberXRows;
02512     double * storedUpper = upper_ + numberColumns_+numberXRows;
02513     double * storedValue = solution_ + numberColumns_+numberXRows;
02514     int * index = array1->getIndices();
02515     double * modifiedCost = array1->denseVector();
02516     // Compute duals
02517     info->createGradient(this);
02518     double * gradient = info->gradient();
02519     // fill in as if linear
02520     // will not be correct unless complementary - but that should not matter
02521     // Just save sj value in that case
02522     //double saveValue=0.0;
02523     //int crucialSj = info->crucialSj();
02524     //if (crucialSj>=0)
02525     int number=0;
02526     int iRow;
02527     for (iRow=0;iRow<numberRows_;iRow++) {
02528       int iPivot=pivotVariable_[iRow];
02529       if (gradient[iPivot]) {
02530         modifiedCost[iRow] = gradient[iPivot];
02531         index[number++]=iRow;
02532       }
02533     }
02534     array1->setNumElements(number);
02535     factorization_->updateColumnTranspose(array2,array1);
02536     memcpy(dual_,modifiedCost,numberRows_*sizeof(double));
02537     array1->clear();
02538     memcpy(dj_,gradient,(numberColumns_+numberRows_)*sizeof(double));
02539     matrix_->transposeTimes(-1.0,dual_,dj_,rowScale_,columnScale_);
02540     memset(dj_+numberXColumns,0,(numberXRows+numberQuadraticColumns)*sizeof(double));
02541     // And djs
02542     for (iRow=0;iRow<numberRows_;iRow++) {
02543       dj_[numberColumns_+iRow]= cost_[numberColumns_+iRow]+dual_[iRow];
02544     }
02545     double saveSj=0.0;
02546     if (info->crucialSj()>=0) 
02547       saveSj=solution_[info->crucialSj()];
02548     // Set dual solution 
02549     for (iRow=0;iRow<numberQuadraticRows;iRow++) {
02550       solution_[iRow+numberXColumns]=dual_[iRow];
02551     }
02552     // clear sj
02553     int start = numberXColumns+numberQuadraticRows;
02554     memset(solution_+start,0,numberQuadraticColumns*sizeof(double));
02555     memset(dj_+numberXColumns,0,(numberQuadraticRows+numberQuadraticColumns)*sizeof(double));
02556     matrix_->times(-1.0,columnActivityWork_,modifiedCost,rowScale_,columnScale_);
02557     memset(modifiedCost,0,numberXRows*sizeof(double));
02558     // Do costs as rhs and sj solution values
02559     for (iRow=0;iRow<numberQuadraticColumns;iRow++) {
02560       int jSequence = iRow;
02561       double value=cost_[jSequence];
02562       if (fabs(value)>1.0e5) {
02563         assert (getColumnStatus(jSequence)==basic);
02564       }
02565       double value2=-modifiedCost[iRow+numberXRows];
02566       modifiedCost[iRow+numberXRows]=0.0;
02567       jSequence = iRow+start;
02568       if (getColumnStatus(jSequence)!=basic) {
02569         if (fabs(value2-value)>1.0e-3)
02570           solution_[jSequence]=0.0;
02571         value=value2;
02572       } else {
02573         solution_[jSequence]=value-value2;
02574       }
02575       storedCost[iRow]=value;
02576       storedUpper[iRow]=value;
02577       storedValue[iRow]=value;
02578     }
02579     if (info->crucialSj()>=0) 
02580       solution_[info->crucialSj()]=saveSj;
02581   }
02582   if (numberIterations_==-1289) {
02583     int i;
02584     printf ("normal\n");
02585     for (i=0;i<numberRows_+numberColumns_;i++) {
02586       char x='N';
02587       if (getColumnStatus(i)==basic)
02588         x='B';
02589       printf("CH %d %c sol %g dj %g\n",i,x,solution_[i],dj_[i]);
02590     }
02591   }
02592 }
02593 
02594 int 
02595 ClpSimplexPrimalQuadratic::checkComplementarity (ClpQuadraticInfo * info,
02596                             CoinIndexedVector * array1, CoinIndexedVector * array2)
02597 {
02598   createDjs(info,array1,array2);
02599   int numberXColumns = info->numberXColumns();
02600   int numberXRows = info->numberXRows();
02601   int start=numberXColumns+numberXRows;
02602   numberDualInfeasibilities_=0;
02603   sumDualInfeasibilities_=0.0;
02604   // Compute objective function from scratch
02605   const CoinPackedMatrix * quadratic = 
02606     info->quadraticObjective();
02607   const int * columnQuadratic = quadratic->getIndices();
02608   const int * columnQuadraticStart = quadratic->getVectorStarts();
02609   const int * columnQuadraticLength = quadratic->getVectorLengths();
02610   const double * quadraticElement = quadratic->getElements();
02611   const double * originalCost = info->linearObjective();
02612   int iColumn;
02613   objectiveValue_=0.0;
02614   double infeasCost=0.0;
02615   double linearCost=0.0;
02616   int number0=0,number1=0,number2=0;
02617 #if 0
02618   int numberNSj=0;
02619   for (iColumn=numberXColumns+info->numberQuadraticRows();iColumn<numberColumns_;iColumn++) {
02620     if (getColumnStatus(iColumn)!=basic)
02621       numberNSj++;
02622   }
02623   printf("NumberN %d\n",numberNSj);
02624 #endif
02625   for (iColumn=0;iColumn<numberXColumns;iColumn++) {
02626     double valueI = solution_[iColumn];
02627     linearCost += valueI*originalCost[iColumn];
02628     double diff =cost_[iColumn]-originalCost[iColumn];
02629     // WE are always feasible so look at low not up!
02630     if (diff>0.0) {
02631       double above = valueI-lower_[iColumn];
02632       assert(above>=0.0);
02633       infeasCost += diff*above;
02634     } else if (diff<0.0) {
02635       double below = upper_[iColumn]-valueI;
02636       assert(below>=0.0);
02637       infeasCost -= diff*below;
02638     }
02639     int j;
02640     for (j=columnQuadraticStart[iColumn];
02641          j<columnQuadraticStart[iColumn]+columnQuadraticLength[iColumn];j++) {
02642       int jColumn = columnQuadratic[j];
02643       double valueJ = solution_[jColumn];
02644       double elementValue = 0.5*quadraticElement[j];
02645       objectiveValue_ += valueI*valueJ*elementValue;
02646     }
02647     int jSequence = iColumn+start;
02648     double value=dj_[iColumn];
02649     ClpSimplex::Status status = getColumnStatus(iColumn);
02650     if (status!=basic&&jSequence>=0) {
02651       if (getColumnStatus(jSequence)==basic) 
02652         number1++;
02653       else
02654         number0++;
02655     }
02656     
02657     switch(status) {
02658       
02659     case ClpSimplex::basic:
02660       if (getColumnStatus(jSequence)==basic) {
02661         handler_->message(CLP_QUADRATIC_BOTH,messages_)
02662           <<"Structural"<<iColumn
02663           <<solution_[iColumn]<<jSequence<<solution_[jSequence]
02664           <<CoinMessageEol;
02665         number2++;
02666         assert (info->crucialSj()>=0);
02667         assert (info->crucialSj()==iColumn||info->crucialSj()==jSequence);
02668       } else {
02669         number1++;
02670       }
02671       break;
02672     case ClpSimplex::isFixed:
02673       break;
02674     case ClpSimplex::isFree:
02675     case ClpSimplex::superBasic:
02676       if (fabs(value)>dualTolerance_) {
02677         sumDualInfeasibilities_ += fabs(value)-dualTolerance_;
02678         numberDualInfeasibilities_++;
02679       }
02680       break;
02681     case ClpSimplex::atUpperBound:
02682       if (value>dualTolerance_) {
02683         sumDualInfeasibilities_ += value-dualTolerance_;
02684         numberDualInfeasibilities_++;
02685       }
02686       break;
02687     case ClpSimplex::atLowerBound:
02688       if (value<-dualTolerance_) {
02689         sumDualInfeasibilities_ -= value+dualTolerance_;
02690         numberDualInfeasibilities_++;
02691       }
02692     }
02693   }
02694   int offset = numberXColumns;
02695   int iRow;
02696   for (iRow=0;iRow<numberXRows;iRow++) {
02697     int iColumn = iRow + numberColumns_;
02698     double diff =cost_[iColumn];
02699     double valueI = solution_[iColumn];
02700     if (diff>0.0) {
02701       double above = valueI-lower_[iColumn];
02702       assert(above>=0.0);
02703       infeasCost += diff*above;
02704     } else if (diff<0.0) {
02705       double below = upper_[iColumn]-valueI;
02706       assert(below>=0.0);
02707       infeasCost -= diff*below;
02708     }
02709     int jSequence = iRow+offset;
02710     double value=dj_[iRow+numberColumns_];
02711     ClpSimplex::Status status = getRowStatus(iRow);
02712     if (status!=basic) {
02713       if (getColumnStatus(jSequence)==basic) 
02714         number1++;
02715       else
02716         number0++;
02717     }
02718     
02719     switch(status) {
02720       
02721     case ClpSimplex::basic:
02722       if (getColumnStatus(jSequence)==basic) {
02723         printf("Row %d (%g) and %d (%g) both basic\n",
02724                iRow,solution_[iColumn],jSequence,solution_[jSequence]);
02725           number2++;
02726           assert (info->crucialSj()>=0);
02727           assert (info->crucialSj()==iColumn||info->crucialSj()==jSequence);
02728         } else {
02729           number1++;
02730         }
02731       break;
02732     case ClpSimplex::isFixed:
02733       break;
02734     case ClpSimplex::isFree:
02735     case ClpSimplex::superBasic:
02736       if (fabs(value)>dualTolerance_) {
02737         sumDualInfeasibilities_ += fabs(value)-dualTolerance_;
02738         numberDualInfeasibilities_++;
02739       }
02740       break;
02741     case ClpSimplex::atUpperBound:
02742       if (value>dualTolerance_) {
02743         sumDualInfeasibilities_ += value-dualTolerance_;
02744         numberDualInfeasibilities_++;
02745       }
02746       break;
02747     case ClpSimplex::atLowerBound:
02748       if (value<-dualTolerance_) {
02749         sumDualInfeasibilities_ -= value+dualTolerance_;
02750         numberDualInfeasibilities_++;
02751       }
02752     }
02753   }
02754   //printf("number 0 - %d, 1 - %d, 2 - %d\n",number0,number1,number2);
02755   objectiveValue_ += linearCost+infeasCost;
02756   assert (infeasCost>=0.0);
02757   sumOfRelaxedDualInfeasibilities_ =sumDualInfeasibilities_;
02758   // But not zero if cleanup iteration
02759   if (info->sequenceIn()>=0&&!numberDualInfeasibilities_)
02760     numberDualInfeasibilities_=1;
02761   numberDualInfeasibilitiesWithoutFree_= numberDualInfeasibilities_;
02762   info->setInfeasCost(infeasCost);
02763   return numberDualInfeasibilities_;
02764 }
02765   
02766 /* This creates the large version of QP and
02767       fills in quadratic information
02768 */
02769 ClpSimplexPrimalQuadratic * 
02770 ClpSimplexPrimalQuadratic::makeQuadratic(ClpQuadraticInfo & info)
02771 {
02772 
02773   // Get list of non linear columns
02774   ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
02775   assert (quadraticObj);
02776   CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective();
02777   if (!quadratic||!quadratic->getNumElements()) {
02778     // no quadratic part
02779     return NULL;
02780   }
02781 
02782   int numberColumns = this->numberColumns();
02783   double * columnLower = this->columnLower();
02784   double * columnUpper = this->columnUpper();
02785   double * objective = this->objective();
02786   double * solution = this->primalColumnSolution();
02787   double * dj = this->dualColumnSolution();
02788   double * pi = this->dualRowSolution();
02789 
02790   int numberRows = this->numberRows();
02791   double * rowLower = this->rowLower();
02792   double * rowUpper = this->rowUpper();
02793 
02794   // and elements
02795   CoinPackedMatrix * matrix = this->matrix();
02796   const int * row = matrix->getIndices();
02797   const int * columnStart = matrix->getVectorStarts();
02798   const double * element =  matrix->getElements();
02799   const int * columnLength = matrix->getVectorLengths();
02800 
02801   int iColumn;
02802   const int * columnQuadratic = quadratic->getIndices();
02803   const int * columnQuadraticStart = quadratic->getVectorStarts();
02804   const int * columnQuadraticLength = quadratic->getVectorLengths();
02805   const double * quadraticElement = quadratic->getElements();
02806 #if 0
02807   // deliberate bad solution
02808   // Change to use phase
02809   //double * saveO = new double[numberColumns];
02810   //memcpy(saveO,objective,numberColumns*sizeof(double));
02811   //memset(objective,0,numberColumns*sizeof(double));
02812   tempMessage messageHandler(this);;
02813   passInMessageHandler(&messageHandler);
02814   factorization()->maximumPivots(1);
02815   primal();
02816   CoinMessageHandler handler2;
02817   passInMessageHandler(&handler2);
02818   factorization()->maximumPivots(100);
02819   setMaximumIterations(1000);
02820 #endif
02821   //memcpy(objective,saveO,numberColumns*sizeof(double));
02822   // Get a feasible solution 
02823   //printf("For testing - deliberate bad solution\n");
02824   //columnUpper[0]=0.0;
02825   //columnLower[0]=0.0;
02826   //quadraticSLP(50,1.0e-4);
02827   //primal(1);
02828   //columnUpper[0]=COIN_DBL_MAX;
02829   
02830   // Create larger problem
02831   // First workout how many rows extra
02832   info=ClpQuadraticInfo(this);
02833   quadratic = info.quadraticObjective();
02834   int numberQuadratic = info.numberQuadraticColumns();
02835   int newNumberRows = numberRows+numberQuadratic;
02836   int newNumberColumns = numberColumns + numberRows + numberQuadratic;
02837   int numberElements = 2*matrix->getNumElements()
02838     +2*quadratic->getNumElements()
02839     + numberQuadratic;
02840   double * elements2 = new double[numberElements];
02841   int * start2 = new int[newNumberColumns+1];
02842   int * row2 = new int[numberElements];
02843   double * objective2 = new double[newNumberColumns];
02844   double * columnLower2 = new double[newNumberColumns];
02845   double * columnUpper2 = new double[newNumberColumns];
02846   double * rowLower2 = new double[newNumberRows];
02847   double * rowUpper2 = new double[newNumberRows];
02848   memcpy(rowLower2,rowLower,numberRows*sizeof(double));
02849   memcpy(rowUpper2,rowUpper,numberRows*sizeof(double));
02850   int iRow;
02851   for (iRow=0;iRow<numberQuadratic;iRow++) {
02852     double cost = objective[iRow];
02853     rowLower2[iRow+numberRows]=cost;
02854     rowUpper2[iRow+numberRows]=cost;
02855   }
02856   memset(objective2,0,newNumberColumns*sizeof(double));
02857   // Get a row copy of quadratic objective in standard format
02858   CoinPackedMatrix copyQ;
02859   copyQ.reverseOrderedCopyOf(*quadratic);
02860   const int * columnQ = copyQ.getIndices();
02861   const CoinBigIndex * rowStartQ = copyQ.getVectorStarts();
02862   const int * rowLengthQ = copyQ.getVectorLengths(); 
02863   const double * elementByRowQ = copyQ.getElements();
02864   // Move solution across
02865   double * solution2 = new double[newNumberColumns];
02866   memset(solution2,0,newNumberColumns*sizeof(double));
02867   newNumberColumns=0;
02868   numberElements=0;
02869   start2[0]=0;
02870   // x
02871   memcpy(dj,objective,numberColumns*sizeof(double));
02872   for (iColumn=0;iColumn<numberColumns;iColumn++) {
02873     // Original matrix
02874     columnLower2[iColumn]=columnLower[iColumn];
02875     columnUpper2[iColumn]=columnUpper[iColumn];
02876     solution2[iColumn]=solution[iColumn];
02877     // Put in cost so we know it
02878     objective2[iColumn]=objective[iColumn];
02879     int j;
02880     for (j=columnStart[iColumn];
02881          j<columnStart[iColumn]+columnLength[iColumn];
02882          j++) {
02883       elements2[numberElements]=element[j];
02884       row2[numberElements++]=row[j];
02885     }
02886     // Quadratic and modify djs
02887     for (j=columnQuadraticStart[iColumn];
02888          j<columnQuadraticStart[iColumn]+columnQuadraticLength[iColumn];
02889          j++) {
02890       int jColumn = columnQuadratic[j];
02891       double value = quadraticElement[j];
02892       if (iColumn!=jColumn) 
02893         value *= 0.5;
02894       dj[jColumn] += solution[iColumn]*value;
02895       elements2[numberElements]=-value;
02896       row2[numberElements++]=jColumn+numberRows;
02897     }
02898     for (j=rowStartQ[iColumn];
02899          j<rowStartQ[iColumn]+rowLengthQ[iColumn];
02900          j++) {
02901       int jColumn = columnQ[j];
02902       double value = elementByRowQ[j];
02903       if (iColumn!=jColumn) { 
02904         value *= 0.5;
02905         dj[jColumn] += solution[iColumn]*value;
02906         elements2[numberElements]=-value;
02907         row2[numberElements++]=jColumn+numberRows;
02908       }
02909     }
02910     start2[iColumn+1]=numberElements;
02911   }
02912   newNumberColumns=numberColumns;
02913   // pi
02914   int numberQuadraticRows = info.numberQuadraticRows();
02915   // Get a row copy in standard format
02916   CoinPackedMatrix copy;
02917   copy.reverseOrderedCopyOf(*(this->matrix()));
02918   // get matrix data pointers
02919   const int * column = copy.getIndices();
02920   const CoinBigIndex * rowStart = copy.getVectorStarts();
02921   const int * rowLength = copy.getVectorLengths(); 
02922   const double * elementByRow = copy.getElements();
02923   for (iRow=0;iRow<numberRows;iRow++) {
02924     solution2[newNumberColumns]=pi[iRow];
02925     double value = pi[iRow];
02926     columnLower2[newNumberColumns]=-COIN_DBL_MAX;
02927     columnUpper2[newNumberColumns]=COIN_DBL_MAX;
02928     int j;
02929     for (j=rowStart[iRow];
02930          j<rowStart[iRow]+rowLength[iRow];
02931          j++) {
02932       double elementValue=elementByRow[j];
02933       int jColumn = column[j];
02934       if (jColumn>=0) {
02935         elements2[numberElements]=elementValue;
02936         row2[numberElements++]=jColumn+numberRows;
02937       }
02938       dj[jColumn]-= value*elementValue;
02939     }
02940 #ifndef CORRECT_ROW_COUNTS
02941     newNumberColumns++;
02942     start2[newNumberColumns]=numberElements;
02943 #else
02944     if (numberElements>start2[newNumberColumns]) {
02945       newNumberColumns++;
02946       start2[newNumberColumns]=numberElements;
02947     }
02948 #endif
02949   }
02950   // djs 
02951   for (iColumn=0;iColumn<numberQuadratic;iColumn++) {
02952     columnLower2[newNumberColumns]=-COIN_DBL_MAX;
02953     columnUpper2[newNumberColumns]=COIN_DBL_MAX;
02954     solution2[newNumberColumns]=dj[iColumn];
02955     elements2[numberElements]=1.0;
02956     row2[numberElements++]=iColumn+numberRows;
02957     newNumberColumns++;
02958     start2[newNumberColumns]=numberElements;
02959   }
02960   // Create model 
02961   ClpSimplex * model2 = new ClpSimplex(*this);
02962   model2->resize(0,0);
02963   model2->loadProblem(newNumberColumns,newNumberRows,
02964                      start2,row2, elements2,
02965                      columnLower2,columnUpper2,
02966                      objective2,
02967                      rowLower2,rowUpper2);
02968   delete [] rowLower2;
02969   delete [] rowUpper2;
02970   delete [] columnLower2;
02971   delete [] columnUpper2;
02972   // Now create expanded quadratic objective for use in primalRow
02973   // Later pack down in some way
02974   start2[0]=0;
02975   numberElements=0;
02976   for (iColumn=0;iColumn<numberColumns;iColumn++) {
02977     // Quadratic
02978     int j;
02979     for (j=columnQuadraticStart[iColumn];
02980          j<columnQuadraticStart[iColumn]+columnQuadraticLength[iColumn];
02981          j++) {
02982       int jColumn = columnQuadratic[j];
02983       double value = quadraticElement[j];
02984       if (iColumn!=jColumn) 
02985         value *= 0.5;
02986       elements2[numberElements]=value;
02987       row2[numberElements++]=jColumn;
02988     }
02989     for (j=rowStartQ[iColumn];
02990          j<rowStartQ[iColumn]+rowLengthQ[iColumn];
02991          j++) {
02992       int jColumn = columnQ[j];
02993       double value = elementByRowQ[j];
02994       if (iColumn!=jColumn) { 
02995         value *= 0.5;
02996         elements2[numberElements]=value;
02997         row2[numberElements++]=jColumn;
02998       }
02999     }
03000     start2[iColumn+1]=numberElements;
03001   }
03002   // and pad
03003   //for (;iColumn<newNumberColumns;iColumn++)
03004   //start2[iColumn+1]=numberElements;
03005   // Load up objective with expanded linear
03006   ClpQuadraticObjective * obj = 
03007     new ClpQuadraticObjective(objective2,numberColumns,
03008                               start2,row2,elements2,newNumberColumns);
03009   delete [] objective2;
03010   info.setOriginalObjective(obj);
03011   //model2->loadQuadraticObjective(newNumberColumns,start2,row2,elements2);
03012   delete [] start2;
03013   delete [] row2;
03014   delete [] elements2;
03015   model2->allSlackBasis();
03016   //model2->scaling(false);
03017   //printf("scaling off\n");
03018   model2->setLogLevel(this->logLevel());
03019   // Move solution across
03020   memcpy(model2->primalColumnSolution(),solution2,
03021          newNumberColumns*sizeof(double));
03022   columnLower2 = model2->columnLower();
03023   columnUpper2 = model2->columnUpper();
03024   delete [] solution2;
03025   solution2 = model2->primalColumnSolution();
03026   // Compute row activities and check feasible
03027   double * rowSolution2 = model2->primalRowSolution();
03028   memset(rowSolution2,0,newNumberRows*sizeof(double));
03029   model2->times(1.0,solution2,rowSolution2);
03030   rowLower2 = model2->rowLower();
03031   rowUpper2 = model2->rowUpper();
03032 #if 0
03033   // redo as Dantzig says 
03034   for (iColumn=0;iColumn<numberColumns;iColumn++) {
03035     Status xStatus = getColumnStatus(iColumn);
03036     bool isSuperBasic;
03037     int iS = iColumn+newNumberRows;
03038     model2->setColumnStatus(iColumn,xStatus);
03039     if (xStatus==basic) {
03040       model2->setColumnStatus(iS,isFree);
03041       solution2[iS]=0.0;
03042     } else {
03043       model2->setColumnStatus(iS,basic);
03044     }
03045     // take slack out on equality rows
03046     model2->setRowBasic(iColumn+numberRows,superBasic);
03047   }
03048   for (iRow=0;iRow<numberRows;iRow++) {
03049     Status rowStatus = getRowStatus(iRow);
03050     model2->setRowStatus(iRow,rowStatus);
03051     if (rowStatus!=basic) {
03052       model2->setColumnStatus(iRow+numberColumns,basic); // make dual basic
03053     }
03054     assert (rowSolution2[iRow]>=rowLower2[iRow]-primalTolerance_);
03055     assert (rowSolution2[iRow]<=rowUpper2[iRow]+primalTolerance_);
03056   }
03057   // why ?? - take duals out and adjust
03058   for (iRow=0;iRow<numberRows;iRow++) {
03059     model2->setRowStatus(iRow,basic);
03060     model2->setColumnStatus(iRow+numberColumns,superBasic);
03061     solution2[iRow+numberColumns]=0.0;
03062   }
03063 #else
03064   for (iRow=0;iRow<numberRows;iRow++) {
03065     assert (rowSolution2[iRow]>=rowLower2[iRow]-primalTolerance_);
03066     assert (rowSolution2[iRow]<=rowUpper2[iRow]+primalTolerance_);
03067     model2->setRowStatus(iRow,basic);
03068     int jRow = iRow;
03069     model2->setColumnStatus(jRow+numberColumns,superBasic);
03070     solution2[jRow+numberColumns]=0.0;
03071   }
03072   for (iColumn=numberQuadraticRows+numberColumns;iColumn<newNumberColumns;iColumn++) {
03073     model2->setColumnStatus(iColumn,basic);
03074     model2->setRowStatus(iColumn-numberQuadraticRows-numberColumns+numberRows,isFixed);
03075   }
03076 #endif
03077   memset(rowSolution2,0,newNumberRows*sizeof(double));
03078   model2->times(1.0,solution2,rowSolution2);
03079   for (iColumn=0;iColumn<numberQuadratic;iColumn++) {
03080     int iS = iColumn+numberColumns+numberQuadraticRows;
03081     int iRow = iColumn+numberRows;
03082     double value = rowSolution2[iRow];
03083     if (value>rowUpper2[iRow]) {
03084       rowSolution2[iRow] = rowUpper2[iRow];
03085       solution2[iS]-=value-rowUpper2[iRow];
03086     } else {
03087       rowSolution2[iRow] = rowLower2[iRow];
03088       solution2[iS]-=value-rowLower2[iRow];
03089     }
03090   }
03091 
03092   
03093   // See if any s sub j have wrong sign and/or use djs from infeasibility objective
03094   double objectiveOffset;
03095   getDblParam(ClpObjOffset,objectiveOffset);
03096   double objValue = -objectiveOffset;
03097   for (iColumn=0;iColumn<numberColumns;iColumn++) 
03098     objValue += objective[iColumn]*solution2[iColumn];
03099   for (iColumn=0;iColumn<numberColumns;iColumn++) {
03100     double valueI = solution2[iColumn];
03101     int j;
03102     for (j=columnQuadraticStart[iColumn];
03103          j<columnQuadraticStart[iColumn]+columnQuadraticLength[iColumn];j++) {
03104       int jColumn = columnQuadratic[j];
03105       double valueJ = solution2[jColumn];
03106       double elementValue = quadraticElement[j];
03107       objValue += 0.5*valueI*valueJ*elementValue;
03108     }
03109   }
03110   printf("Objective value %g\n",objValue);
03111   //for (iColumn=0;iColumn<newNumberColumns;iColumn++) 
03112   //printf("%d %g\n",iColumn,solution2[iColumn]);
03113   return (ClpSimplexPrimalQuadratic *) model2;
03114 }
03115 
03116 // This moves solution back and deletes information
03117 int 
03118 ClpSimplexPrimalQuadratic::endQuadratic(ClpSimplexPrimalQuadratic * quadraticModel,
03119                    ClpQuadraticInfo & info)
03120 {
03121   memcpy(dualRowSolution(),quadraticModel->dualRowSolution(),numberRows_*sizeof(double));
03122   const double * solution2 = quadraticModel->primalColumnSolution();
03123   memcpy(primalColumnSolution(),solution2,numberColumns_*sizeof(double));
03124   memset(quadraticModel->primalRowSolution(),0,
03125          quadraticModel->numberRows()*sizeof(double));
03126   quadraticModel->times(1.0,quadraticModel->primalColumnSolution(),
03127                quadraticModel->primalRowSolution());
03128 
03129   int iColumn;
03130   double objectiveOffset;
03131   getDblParam(ClpObjOffset,objectiveOffset);
03132   double objValue = -objectiveOffset;
03133   double * objective = this->objective();
03134   const double * pi = dualRowSolution();
03135   for (iColumn=0;iColumn<numberColumns_;iColumn++) 
03136     objValue += objective[iColumn]*solution2[iColumn];
03137   ClpQuadraticObjective * quadraticObj = (dynamic_cast< ClpQuadraticObjective*>(objective_));
03138   assert (quadraticObj);
03139   CoinPackedMatrix * quadratic = quadraticObj->quadraticObjective();
03140   double * dj = dualColumnSolution();
03141   // Matrix for linear stuff
03142   const int * row = matrix_->getIndices();
03143   const int * columnStart = matrix_->getVectorStarts();
03144   const double * element =  matrix_->getElements();
03145   const int * columnLength = matrix_->getVectorLengths();
03146   if (quadratic) {
03147     const int * columnQuadratic = quadratic->getIndices();
03148     const int * columnQuadraticStart = quadratic->getVectorStarts();
03149     const int * columnQuadraticLength = quadratic->getVectorLengths();
03150     const double * quadraticElement = quadratic->getElements();
03151     int start = info.numberQuadraticRows()+numberColumns_;
03152     for (iColumn=0;iColumn<numberColumns_;iColumn++) {
03153       int jColumn = iColumn;
03154       double valueI=solution2[iColumn];
03155       double value;
03156       if (jColumn>=0) {
03157         jColumn += start;
03158         value = solution2[jColumn];
03159       } else {
03160         value=objective[iColumn];
03161         int j;
03162         for (j=columnStart[iColumn];j<columnStart[iColumn]+columnLength[iColumn]; j++) {
03163           int iRow = row[j];
03164           value -= element[j]*pi[iRow];
03165         }
03166       }
03167       dj[iColumn]=value;
03168       Status status = quadraticModel->getColumnStatus(iColumn);
03169       setColumnStatus(iColumn,status);
03170       if (status==basic) {
03171         assert(fabs(value)<1.0e-2);
03172       }
03173       int j;
03174       for (j=columnQuadraticStart[iColumn];
03175            j<columnQuadraticStart[iColumn]+columnQuadraticLength[iColumn];j++) {
03176         int jColumn = columnQuadratic[j];
03177         double valueJ = solution2[jColumn];
03178         double elementValue = quadraticElement[j];
03179         objValue += 0.5*valueI*valueJ*elementValue;
03180       }
03181     }
03182     objectiveValue_ = objValue + objectiveOffset;
03183   } else {
03184     // Do linear bit anyway
03185     for (iColumn=0;iColumn<numberColumns_;iColumn++) {
03186       double value=objective[iColumn];
03187       int j;
03188       for (j=columnStart[iColumn];j<columnStart[iColumn]+columnLength[iColumn]; j++) {
03189         int iRow = row[j];
03190         value -= element[j]*pi[iRow];
03191       }
03192       dj[iColumn]=value;
03193       Status status = quadraticModel->getColumnStatus(iColumn);
03194       setColumnStatus(iColumn,status);
03195     }
03196   }
03197   // and row status
03198   int iRow;
03199   for (iRow=0;iRow<numberRows_;iRow++) {
03200     Status status = quadraticModel->getRowStatus(iRow);
03201     setRowStatus(iRow,status);
03202   }
03203   printf("Objective value %g\n",objValue);
03204   return 0;
03205 }
03206 
03208 ClpQuadraticInfo::ClpQuadraticInfo()
03209   : originalObjective_(NULL),
03210     basicRow_(NULL),
03211     impliedSj_(NULL),
03212     currentSequenceIn_(-1),
03213     crucialSj_(-1),
03214     validSequenceIn_(-1),
03215     validCrucialSj_(-1),
03216     currentPhase_(-1),
03217     currentSolution_(NULL),
03218     validPhase_(-1),
03219     validSolution_(NULL),
03220     djWeight_(NULL),
03221     gradient_(NULL),
03222     numberXRows_(-1),
03223     numberXColumns_(-1),
03224     numberQuadraticColumns_(0),
03225     numberQuadraticRows_(0),
03226     infeasCost_(0.0)
03227 {
03228 }
03229 // Constructor from original model
03230 ClpQuadraticInfo::ClpQuadraticInfo(const ClpSimplex * model)
03231   : originalObjective_(NULL),
03232     basicRow_(NULL),
03233     impliedSj_(NULL),
03234     currentSequenceIn_(-1),
03235     crucialSj_(-1),
03236     validSequenceIn_(-1),
03237     validCrucialSj_(-1),
03238     currentPhase_(-1),
03239     currentSolution_(NULL),
03240     validPhase_(-1),
03241     validSolution_(NULL),
03242     djWeight_(NULL),
03243     gradient_(NULL),
03244     numberXRows_(-1),
03245     numberXColumns_(-1),
03246     numberQuadraticColumns_(0),
03247     numberQuadraticRows_(0),
03248     infeasCost_(0.0)
03249 {
03250   if (model) {
03251     numberXRows_ = model->numberRows();
03252     numberXColumns_ = model->numberColumns();
03253     //ClpQuadraticObjective *originalObjective = (dynamic_cast< ClpQuadraticObjective*>(model->objectiveAsObject()));
03254     //assert (originalObjective);
03255     originalObjective_ = (dynamic_cast< ClpQuadraticObjective*>(model->objectiveAsObject()));
03256     assert (originalObjective_);
03257     impliedSj_ = new int[numberXColumns_];
03258     basicRow_ = new int[numberXColumns_];
03259     int i;
03260     numberQuadraticColumns_=numberXColumns_;
03261     numberQuadraticRows_=numberXRows_;
03262     int numberColumns = numberQuadraticRows_+numberXColumns_+numberQuadraticColumns_;
03263     int numberRows = numberXRows_+numberQuadraticColumns_;
03264     int size = numberRows+numberColumns;
03265     djWeight_ = new double [size];
03266     basicRow_ = new int[size];
03267     for (i=0;i<size;i++)
03268       djWeight_[i]=1.0;
03269   }
03270 }
03271 // Destructor
03272 ClpQuadraticInfo:: ~ClpQuadraticInfo()
03273 {
03274   delete [] impliedSj_;
03275   delete [] basicRow_;
03276   delete [] currentSolution_;
03277   delete [] validSolution_;
03278   delete [] djWeight_;
03279   delete [] gradient_;
03280 }
03281 // Copy
03282 ClpQuadraticInfo::ClpQuadraticInfo(const ClpQuadraticInfo& rhs)
03283   : originalObjective_(rhs.originalObjective_),
03284     basicRow_(NULL),
03285     impliedSj_(NULL),
03286     currentSequenceIn_(rhs.currentSequenceIn_),
03287     crucialSj_(rhs.crucialSj_),
03288     validSequenceIn_(rhs.validSequenceIn_),
03289     validCrucialSj_(rhs.validCrucialSj_),
03290     currentPhase_(rhs.currentPhase_),
03291     currentSolution_(NULL),
03292     validPhase_(rhs.validPhase_),
03293     validSolution_(NULL),
03294     djWeight_(NULL),
03295     gradient_(NULL),
03296     numberXRows_(rhs.numberXRows_),
03297     numberXColumns_(rhs.numberXColumns_),
03298     numberQuadraticColumns_(rhs.numberQuadraticColumns_),
03299     numberQuadraticRows_(rhs.numberQuadraticRows_),
03300     infeasCost_(rhs.infeasCost_)
03301 {
03302   if (numberXColumns_) {
03303     int numberColumns = numberQuadraticRows_+numberXColumns_+numberQuadraticColumns_;
03304     int numberRows = numberXRows_+numberQuadraticColumns_;
03305     int size = numberRows+numberColumns;
03306     impliedSj_ = new int[numberXColumns_];
03307     memcpy(impliedSj_,rhs.impliedSj_,numberXColumns_*sizeof(int));
03308     basicRow_ = new int [size];
03309     memcpy(basicRow_,rhs.basicRow_,size*sizeof(int));
03310     if (rhs.currentSolution_) {
03311       currentSolution_ = new double [size];
03312       memcpy(currentSolution_,rhs.currentSolution_,size*sizeof(double));
03313     } else {
03314       currentSolution_ = NULL;
03315     }
03316     if (rhs.validSolution_) {
03317       validSolution_ = new double [size];
03318       memcpy(validSolution_,rhs.validSolution_,size*sizeof(double));
03319     } else {
03320       validSolution_ = NULL;
03321     }
03322     if (rhs.djWeight_) {
03323       djWeight_ = new double [size];
03324       memcpy(djWeight_,rhs.djWeight_,size*sizeof(double));
03325     } else {
03326       djWeight_ = NULL;
03327     }
03328     if (rhs.gradient_) {
03329       gradient_ = new double [size];
03330       memcpy(gradient_,rhs.gradient_,size*sizeof(double));
03331     } else {
03332       gradient_ = NULL;
03333     }
03334   }
03335 }
03336 // Assignment
03337 ClpQuadraticInfo & 
03338 ClpQuadraticInfo::operator=(const ClpQuadraticInfo&rhs)
03339 {
03340   if (this != &rhs) {
03341     originalObjective_ = rhs.originalObjective_;
03342     delete [] impliedSj_;
03343     delete [] basicRow_;
03344     delete [] currentSolution_;
03345     delete [] validSolution_;
03346     delete [] djWeight_;
03347     delete [] gradient_;
03348     currentSequenceIn_ = rhs.currentSequenceIn_;
03349     crucialSj_ = rhs.crucialSj_;
03350     validSequenceIn_ = rhs.validSequenceIn_;
03351     validCrucialSj_ = rhs.validCrucialSj_;
03352     currentPhase_ = rhs.currentPhase_;
03353     validPhase_ = rhs.validPhase_;
03354     numberXRows_ = rhs.numberXRows_;
03355     numberXColumns_ = rhs.numberXColumns_;
03356     infeasCost_=rhs.infeasCost_;
03357     numberQuadraticColumns_=rhs.numberQuadraticColumns_;
03358     numberQuadraticRows_=rhs.numberQuadraticRows_;
03359     int numberColumns = numberQuadraticRows_+numberXColumns_+numberQuadraticColumns_;
03360     int numberRows = numberXRows_+numberQuadraticColumns_;
03361     int size = numberRows+numberColumns;
03362     impliedSj_ = new int[numberXColumns_];
03363     memcpy(impliedSj_,rhs.impliedSj_,numberXColumns_*sizeof(int));
03364     basicRow_ = new int [size];
03365     memcpy(basicRow_,rhs.basicRow_,size*sizeof(int));
03366     if (rhs.currentSolution_) {
03367       currentSolution_ = new double [size];
03368       memcpy(currentSolution_,rhs.currentSolution_,size*sizeof(double));
03369     } else {
03370       currentSolution_ = NULL;
03371     }
03372     if (rhs.validSolution_) {
03373       validSolution_ = new double [size];
03374       memcpy(validSolution_,rhs.validSolution_,size*sizeof(double));
03375     } else {
03376       validSolution_ = NULL;
03377     }
03378     if (rhs.djWeight_) {
03379       djWeight_ = new double [size];
03380       memcpy(djWeight_,rhs.djWeight_,size*sizeof(double));
03381     } else {
03382       djWeight_ = NULL;
03383     }
03384     if (rhs.gradient_) {
03385       gradient_ = new double [size];
03386       memcpy(gradient_,rhs.gradient_,size*sizeof(double));
03387     } else {
03388       gradient_ = NULL;
03389     }
03390   }
03391   return *this;
03392 }
03393 // Save current In and Sj status
03394  void 
03395 ClpQuadraticInfo::saveStatus()
03396 {
03397   validSequenceIn_ = currentSequenceIn_;
03398   validCrucialSj_ = crucialSj_;
03399   validPhase_ = currentPhase_;
03400   int numberColumns = numberQuadraticRows_+numberXColumns_+numberQuadraticColumns_;
03401   int numberRows = numberXRows_+numberQuadraticColumns_;
03402   int size = numberRows+numberColumns;
03403   if (currentSolution_) {
03404     if (!validSolution_) 
03405       validSolution_ = new double [size];
03406     memcpy(validSolution_,currentSolution_,size*sizeof(double));
03407   }
03408 }
03409 // Restore previous
03410 void 
03411 ClpQuadraticInfo::restoreStatus()
03412 {
03413   currentSequenceIn_ = validSequenceIn_;
03414   crucialSj_ = validCrucialSj_;
03415   currentPhase_ = validPhase_;
03416   delete [] currentSolution_;
03417   currentSolution_ = validSolution_;
03418   validSolution_=NULL;
03419 }
03420 void 
03421 ClpQuadraticInfo::setCurrentSolution(const double * solution)
03422 {
03423   if (currentPhase_) {
03424     int numberColumns = numberQuadraticRows_+numberXColumns_+numberQuadraticColumns_;
03425     int numberRows = numberXRows_+numberQuadraticColumns_;
03426     int size = numberRows+numberColumns;
03427     if (!currentSolution_) 
03428       currentSolution_ = new double [size];
03429     memcpy(currentSolution_,solution,size*sizeof(double));
03430   } else {
03431     delete [] currentSolution_;
03432     currentSolution_=NULL;
03433   }
03434 }
03435 // Quadratic objective
03436 CoinPackedMatrix * 
03437 ClpQuadraticInfo::quadraticObjective() const     
03438 { 
03439   return originalObjective_->quadraticObjective();
03440 }
03441 // Linear objective
03442 double * 
03443 ClpQuadraticInfo::linearObjective() const     
03444 { 
03445   return originalObjective_->linearObjective();
03446 }
03447 void 
03448 ClpQuadraticInfo::createGradient(ClpSimplex * model)
03449 {
03450   int numberColumns = numberQuadraticRows_+numberXColumns_+numberQuadraticColumns_;
03451   int numberRows = numberXRows_+numberQuadraticColumns_;
03452   int size = numberRows+numberColumns;
03453   if (!gradient_)
03454     gradient_= new double[size];
03455   memcpy(gradient_,model->costRegion(),size*sizeof(double));
03456   double * solution = model->solutionRegion();
03457   const CoinPackedMatrix * quadratic = quadraticObjective();
03458   const int * columnQuadratic = quadratic->getIndices();
03459   const int * columnQuadraticStart = quadratic->getVectorStarts();
03460   const int * columnQuadraticLength = quadratic->getVectorLengths();
03461   const double * quadraticElement = quadratic->getElements();
03462   // get current costs
03463   int jSequence;
03464   for (jSequence=0;jSequence<numberQuadraticColumns_;jSequence++) {
03465     int iSequence = jSequence;
03466     // get current gradient
03467     double coeff1=gradient_[iSequence];
03468     int j;
03469     for (j=columnQuadraticStart[iSequence];
03470          j<columnQuadraticStart[iSequence]+columnQuadraticLength[iSequence];j++) {
03471       int jColumn = columnQuadratic[j];
03472       double valueJ = solution[jColumn];
03473       // maybe this is just if jColumn basic ??
03474       double elementValue = quadraticElement[j];
03475       double addValue = valueJ*elementValue;
03476       coeff1 += addValue;
03477     }
03478     gradient_[iSequence]=coeff1;
03479   }
03480 }

Generated on Wed Dec 3 14:37:35 2003 for CLP by doxygen 1.3.5