00001
00020 #include "OSCsdpSolver.h"
00021 #include "OSFileUtil.h"
00022 #include "OSInstance.h"
00023 #include "OSOption.h"
00024 #include "OSGeneral.h"
00025 #include "OSMatrix.h"
00026 #include "OSrLReader.h"
00027 #include "OSOutput.h"
00028 #include "OSParameters.h"
00029 #include "OSMathUtil.h"
00030
00031 #include "CoinTime.hpp"
00032
00033 #include <map>
00034
00035 #include <iostream>
00036 #ifdef HAVE_CTIME
00037 # include <ctime>
00038 #else
00039 # ifdef HAVE_TIME_H
00040 # include <time.h>
00041 # else
00042 # error "don't have header file for time"
00043 # endif
00044 #endif
00045
00046 using std::cout;
00047 using std::endl;
00048 using std::ostringstream;
00049
00050
00051 CsdpSolver::CsdpSolver()
00052 {
00053 #ifndef NDEBUG
00054 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_debug,
00055 "inside CsdpSolver constructor\n");
00056 #endif
00057 osrlwriter = new OSrLWriter();
00058 osresult = new OSResult();
00059 m_osilreader = NULL;
00060 m_osolreader = NULL;
00061 csdpErrorMsg = new std::string("");
00062 }
00063
00064 CsdpSolver::~CsdpSolver()
00065 {
00066 #ifndef NDEBUG
00067 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_debug, "inside CsdpSolver destructor\n");
00068 #endif
00069 if(m_osilreader != NULL) delete m_osilreader;
00070 m_osilreader = NULL;
00071 if(m_osolreader != NULL) delete m_osolreader;
00072 m_osolreader = NULL;
00073 delete osresult;
00074 osresult = NULL;
00075 delete osrlwriter;
00076 osrlwriter = NULL;
00077
00078
00079 delete csdpErrorMsg;
00080 #ifndef NDEBUG
00081 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_trace, "Leaving CsdpSolver destructor\n");
00082 #endif
00083 }
00084
00085 void CsdpSolver::buildSolverInstance() throw (ErrorClass)
00086 {
00087 std::ostringstream outStr;
00088 ScalarExpressionTree* tempTree;
00089 OSnLNode *tr;
00090 OSnLMNode *mt;
00091 OSnLMNode *mr;
00092 OSnLMNode *mv;
00093 OSMatrix* tempMtx;
00094
00095 int* blockOffset = NULL;
00096 int* blockSize = NULL;
00097 int* mtxRef = NULL;
00098 bool* isdiag = NULL;
00099 ExpandedMatrixBlocks** mtxBlocks;
00100 try
00101 {
00102 if(osil.length() == 0 && osinstance == NULL) throw ErrorClass("there is no instance");
00103 clock_t start, finish;
00104 double duration;
00105 start = clock();
00106 if(osinstance == NULL)
00107 {
00108 m_osilreader = new OSiLReader();
00109 osinstance = m_osilreader->readOSiL( osil);
00110 }
00111 finish = clock();
00112 duration = (double) (finish - start) / CLOCKS_PER_SEC;
00113
00114
00115
00116
00117
00118
00119 if (osinstance->getNumberOfMatrixVariables() != 1)
00120 throw ErrorClass("There must be one matrixVar object");
00121 if (osinstance->getNumberOfNonlinearExpressions() != osinstance->getConstraintNumber() + 1)
00122 throw ErrorClass("There must be one nonlinear expression for each constraint and objective");
00123 if (osinstance->getLinearConstraintCoefficientNumber() > 0)
00124 throw ErrorClass("Additional linear constraint coefficients are not supported");
00125 if (osinstance->getNumberOfQuadraticTerms() > 0)
00126 throw ErrorClass("Additional quadratic terms are not supported");
00127
00128 char* cType = osinstance->getConstraintTypes();
00129 for (int i=0; i < osinstance->getConstraintNumber(); i++)
00130 if (cType[i] != 'E') throw ErrorClass("Only equality constraints are supported");
00131
00132 std::string* oType = osinstance->getObjectiveMaxOrMins();
00133 if (oType[0] != "max") throw ErrorClass("The problem must be of \"max\" type");
00134
00135
00136 tempTree = osinstance->getNonlinearExpressionTree(-1);
00137 if (tempTree == NULL) throw ErrorClass("Expecting matrixTrace in objective row");
00138 tr = tempTree->m_treeRoot;
00139 if (tr->inodeInt != OS_MATRIX_TRACE)
00140 throw ErrorClass("Expecting matrixTrace in objective row");
00141 mt = tr->m_mMatrixChildren[0];
00142 if (mt->inodeInt != OS_MATRIX_TIMES)
00143 throw ErrorClass("Unsupported expression in objective row");
00144 mr = mt->m_mMatrixChildren[0];
00145 mv = mt->m_mMatrixChildren[1];
00146 if (mr->inodeInt != OS_MATRIX_REFERENCE || mv->inodeInt != OS_MATRIX_VAR)
00147 throw ErrorClass("Unsupported expression in objective row");
00148
00149 mtxRef = new int[osinstance->getConstraintNumber()+1];
00150
00151
00152 mtxRef[0] = ((OSnLMNodeMatrixReference*)mr)->idx;
00153 if (osinstance->instanceData->matrices == NULL)
00154 throw ErrorClass("<matrices> section was never defined");
00155 if (mtxRef[0] < 0 || mtxRef[0] >= osinstance->getMatrixNumber())
00156 throw ErrorClass("Illegal matrix reference");
00157 tempMtx = osinstance->instanceData->matrices->matrix[mtxRef[0]];
00158 if (tempMtx == NULL) throw ErrorClass("A0 matrix was never defined");
00159 if (tempMtx->numberOfRows != tempMtx->numberOfColumns)
00160 throw ErrorClass("A0 matrix must be square and symmetric");
00161 if (tempMtx->getMatrixType() != ENUM_MATRIX_TYPE_constant)
00162 throw ErrorClass("A0 matrix must be of type \"constant\"");
00163
00164 int* rowOffsets = tempMtx->getRowPartition();
00165 int nRowBlocks = tempMtx->getRowPartitionSize();
00166 int* columnOffsets = tempMtx->getColumnPartition();
00167 int nColumnBlocks = tempMtx->getColumnPartitionSize();
00168
00169 int* tempRowOffsets;
00170 int tempNRowBlocks;
00171 int* tempColumnOffsets;
00172 int tempNColumnBlocks;
00173
00174 int i0, itemp, imerge;
00175
00176
00177 for (int i=0; i < osinstance->getConstraintNumber(); i++)
00178 {
00179 tempTree = osinstance->getNonlinearExpressionTree(i);
00180 if (tempTree == NULL) throw ErrorClass("Expecting matrixTrace in constraint row");
00181 tr = tempTree->m_treeRoot;
00182 if (tr->inodeInt != OS_MATRIX_TRACE)
00183 throw ErrorClass("Expecting matrixTrace in constraint row");
00184 mt = tr->m_mMatrixChildren[0];
00185 if (mt->inodeInt != OS_MATRIX_TIMES)
00186 throw ErrorClass("Unsupported expression in constraint row");
00187 mr = mt->m_mMatrixChildren[0];
00188 mv = mt->m_mMatrixChildren[1];
00189 if (mr->inodeInt != OS_MATRIX_REFERENCE || mv->inodeInt != OS_MATRIX_VAR)
00190 throw ErrorClass("Unsupported expression in constraint row");
00191
00192
00193 mtxRef[i+1] = ((OSnLMNodeMatrixReference*)mr)->idx;
00194 if (mtxRef[i+1] < 0 || mtxRef[i+1] >= osinstance->getMatrixNumber())
00195 throw ErrorClass("Illegal matrix reference");
00196 tempMtx = osinstance->instanceData->matrices->matrix[mtxRef[i+1]];
00197 if (tempMtx == NULL) throw ErrorClass("Matrix in constraint was never defined");
00198 if (tempMtx->numberOfRows != tempMtx->numberOfColumns)
00199 throw ErrorClass("Constraint matrix must be square and symmetric");
00200 if (tempMtx->getMatrixType() != ENUM_MATRIX_TYPE_constant)
00201 throw ErrorClass("Constraint matrix must be of type \"constant\"");
00202
00203 tempRowOffsets = tempMtx->getRowPartition();
00204 tempNRowBlocks = tempMtx->getRowPartitionSize();
00205 tempColumnOffsets = tempMtx->getColumnPartition();
00206 tempNColumnBlocks = tempMtx->getColumnPartitionSize();
00207
00208
00209 i0 = 0;
00210 itemp = 0;
00211 imerge = 0;
00212 for (;;)
00213 {
00214 if (rowOffsets[i0] == tempRowOffsets[itemp])
00215 {
00216 if (imerge != i0) rowOffsets[imerge] = rowOffsets[i0];
00217 i0++;
00218 itemp++;
00219 imerge++;
00220 }
00221 else
00222 {
00223 if (rowOffsets[i0] < tempRowOffsets[itemp])
00224 i0++;
00225 else
00226 itemp++;
00227 }
00228 if (i0 >= nRowBlocks || itemp >= tempNRowBlocks)
00229 break;
00230 }
00231 nRowBlocks = imerge;
00232
00233
00234 i0 = 0;
00235 itemp = 0;
00236 imerge = 0;
00237 for (;;)
00238 {
00239 if (columnOffsets[i0] == tempColumnOffsets[itemp])
00240 {
00241 if (imerge != i0) columnOffsets[imerge] = columnOffsets[i0];
00242 i0++;
00243 itemp++;
00244 imerge++;
00245 }
00246 else
00247 {
00248 if (columnOffsets[i0] < tempColumnOffsets[itemp])
00249 i0++;
00250 else
00251 itemp++;
00252 }
00253 if (i0 >= nColumnBlocks || itemp >= tempNColumnBlocks)
00254 break;
00255 }
00256 nColumnBlocks = imerge;
00257 }
00258
00259 blockOffset = new int[nRowBlocks];
00260
00261
00262 int nBlocks;
00263 int jrow = 0;
00264 int jcol = 0;
00265 nBlocks = 0;
00266 for (;;)
00267 {
00268 if (rowOffsets[jrow] == columnOffsets[jcol])
00269 {
00270 blockOffset[nBlocks] = rowOffsets[jrow];
00271 jrow++;
00272 jcol++;
00273 nBlocks++;
00274 }
00275 else
00276 {
00277 if (rowOffsets[jrow] < columnOffsets[jcol])
00278 jrow++;
00279 else
00280 jcol++;
00281 }
00282 if (jrow >= nRowBlocks || jcol >= nColumnBlocks)
00283 break;
00284 }
00285
00286
00287
00288
00289 blockSize = new int[nBlocks];
00290 for (int i=1; i < nBlocks; i++)
00291 {
00292 #ifndef NOSHORTS
00293 if (blockOffset[i] - blockOffset[i-1] >= USHRT_MAX)
00294 throw ErrorClass("This problem is too large to be solved by this version of the code!\n"
00295 + "Recompile without -DUSERSHORTINDS to fix the problem.\n");
00296 #endif
00297 blockSize[i] = blockOffset[i] - blockOffset[i-1];
00298 }
00299
00300 nC_rows = blockOffset[nBlocks-1];
00301 nC_blks = nBlocks-1;
00302 ncon = osinstance->getConstraintNumber();
00303
00304 #ifndef NOSHORTS
00305
00306 if (ncon >= USHRT_MAX)
00307 throw ErrorClass("This problem is too large to be solved by this version of the code!\n"
00308 + "Recompile without -DUSERSHORTINDS to fix the problem.\n");
00309
00310 if (nBlocks >= USHRT_MAX)
00311 throw ErrorClass("This problem is too large to be solved by this version of the code!\n"
00312 + "Recompile without -DUSERSHORTINDS to fix the problem.\n");
00313 #endif
00314
00315 #ifndef BIT64
00316
00317
00318
00319
00320
00321 if (ncon > 23169)
00322 throw ErrorClass("This problem is too large to be solved in 32 bit mode!\n");
00323 #endif
00324
00325
00326 rhsValues = osinstance->getConstraintLowerBounds() - 1;
00327
00328
00329 mtxBlocks = new ExpandedMatrixBlocks*[ncon+1];
00330 GeneralSparseMatrix* tmpBlock;
00331
00332
00333
00334 isdiag = new bool[nBlocks];
00335 for (int i=1; i<nBlocks; i++)
00336 isdiag[i] = true;
00337
00338 for (int j=0; j < ncon+1; j++)
00339 {
00340 mtxBlocks[j] = osinstance->instanceData->matrices->matrix[mtxRef[j]]
00341 ->getBlocks(blockOffset,nBlocks,blockOffset,nBlocks,false,true);
00342
00343 if (!mtxBlocks[j]->isBlockDiagonal())
00344 throw ErrorClass("Constraint matrix must be block-diagonal");
00345
00346 for (int i=0; i<nBlocks-1; i++)
00347 {
00348 tmpBlock = mtxBlocks[j]->getBlock(i,i);
00349 if (tmpBlock != NULL && !(tmpBlock->isDiagonal()))
00350 isdiag[i+1] = false;
00351 }
00352 }
00353
00355 C_matrix.nblocks=nBlocks-1;
00356 C_matrix.blocks = new blockrec[nBlocks];
00357
00359 for (int blk=1; blk < nBlocks; blk++)
00360 {
00361 tmpBlock = mtxBlocks[0]->getBlock(blk-1,blk-1);
00362 int blksz = blockSize[blk];
00363 if (isdiag[blk] == 1)
00364 {
00365
00366 C_matrix.blocks[blk].blocksize = blksz;
00367 C_matrix.blocks[blk].blockcategory = DIAG;
00368 C_matrix.blocks[blk].data.vec = new double[blksz+1];
00369
00370 for (int i=1; i<=blksz; i++)
00371 C_matrix.blocks[blk].data.vec[i] = 0.0;
00372
00373 if (tmpBlock != NULL)
00374 {
00375 for (int i=0; i < tmpBlock->valueSize; i++)
00376 C_matrix.blocks[blk].data.vec[tmpBlock->index[i]+1]
00377 = ((ConstantMatrixValues*)tmpBlock->value)->el[i];
00378 }
00379 }
00380 else
00381 {
00382
00383 C_matrix.blocks[blk].blocksize = blksz;
00384 C_matrix.blocks[blk].blockcategory = MATRIX;
00385 C_matrix.blocks[blk].data.mat = new double[blksz*blksz];
00386
00387 for (int i=1; i<=blksz; i++)
00388 for (int j=1; j<=blksz; j++)
00389 C_matrix.blocks[blk].data.mat[ijtok(i,j,blksz)] = 0.0;
00390
00391 if (tmpBlock != NULL)
00392 {
00393 for (int i=1; i < tmpBlock->startSize; i++)
00394 for (int j=tmpBlock->start[i-1]; j<tmpBlock->start[i]; j++)
00395 {
00396 C_matrix.blocks[blk].data.mat[ijtok(i,tmpBlock->index[j]+1,blksz)]
00397 = ((ConstantMatrixValues*)tmpBlock->value)->el[j];
00398 C_matrix.blocks[blk].data.mat[ijtok(tmpBlock->index[j]+1,i,blksz)]
00399 = ((ConstantMatrixValues*)tmpBlock->value)->el[j];
00400 }
00401 }
00402 }
00403 }
00404
00406 mconstraints = new constraintmatrix[ncon+1];
00407
00409 for (int i=1; i<=ncon; i++)
00410 {
00411 mconstraints[i].blocks = NULL;
00412 }
00413
00414 struct sparseblock *p;
00415 struct sparseblock *q;
00416 struct sparseblock *prev;
00417
00422 for (int i=1; i<=ncon; i++)
00423 {
00424 prev = NULL;
00425 for (int blk=1; blk < nBlocks; blk++)
00426 {
00427 tmpBlock = mtxBlocks[i]->getBlock(blk-1,blk-1);
00428 if (tmpBlock != NULL && tmpBlock->valueSize > 0)
00429 {
00434 p = new sparseblock();
00435 p->numentries = tmpBlock->valueSize;
00436 p->entries = new double[p->numentries+1];
00437 #ifdef NOSHORTS
00438 p->iindices = new int[p->numentries+1];
00439 p->jindices = new int[p->numentries+1];
00440 #else
00441 p->iindices = new unsigned short[p->numentries+1];
00442 p->jindices = new unsigned short[p->numentries+1];
00443 #endif
00444 p->blocknum = blk;
00445 p->blocksize = blockSize[blk];
00446 p->constraintnum = i;
00447 p->next = NULL;
00448 p->nextbyblock = NULL;
00449 if (((p->numentries) > 0.25*(p->blocksize)) && ((p->numentries) > 15))
00450 p->issparse=0;
00451 else
00452 p->issparse=1;
00453
00454
00455 for (int icol=1; icol < tmpBlock->startSize; icol++)
00456 for (int jent=tmpBlock->start[icol-1]; jent<tmpBlock->start[icol]; jent++)
00457 {
00458 p->iindices[jent+1] = icol;
00459 p->jindices[jent+1] = tmpBlock->index[jent] + 1;
00460 p->entries [jent+1] = ((ConstantMatrixValues*)tmpBlock->value)->el[jent];
00461 }
00462
00463 if (prev == NULL)
00464 {
00465 mconstraints[i].blocks = p;
00466 }
00467 else
00468 {
00469 prev->next = p;
00470 prev->nextbyblock = p;
00471 }
00472 prev = p;
00473 }
00474 }
00475 }
00476
00477
00478 if (blockOffset != NULL) delete [] blockOffset;
00479 if (blockSize != NULL) delete [] blockSize;
00480 if (mtxRef != NULL) delete [] mtxRef;
00481 if (isdiag != NULL) delete [] isdiag;
00482 if (mtxBlocks != NULL)
00483 {
00484 for (int i=0; i < ncon+1; i++)
00485 {
00486 if (mtxBlocks[i] != NULL) delete mtxBlocks[i];
00487 mtxBlocks[i] = NULL;
00488 }
00489 delete []mtxBlocks;
00490 }
00491
00492 this->bCallbuildSolverInstance = true;
00493 return;
00494 }
00495
00496 catch(const ErrorClass& eclass)
00497 {
00498 if (blockOffset != NULL) delete [] blockOffset;
00499 if (blockSize != NULL) delete [] blockSize;
00500 if (mtxRef != NULL) delete [] mtxRef;
00501 if (isdiag != NULL) delete [] isdiag;
00502 {
00503 for (int i=0; i <= ncon; i++)
00504 {
00505 if (mtxBlocks[i] != NULL) delete mtxBlocks[i];
00506 mtxBlocks[i] = NULL;
00507 }
00508 delete []mtxBlocks;
00509 }
00510
00511 osresult = new OSResult();
00512 osresult->setGeneralMessage( eclass.errormsg);
00513 osresult->setGeneralStatusType( "error");
00514 osrl = osrlwriter->writeOSrL( osresult);
00515 throw ErrorClass( osrl);
00516 }
00517
00518 }
00519
00520
00521 void CsdpSolver::setSolverOptions() throw(ErrorClass)
00522 {
00533 struct paramstruc params;
00534
00535 std::ostringstream outStr;
00536 std::ostringstream optStr;
00537 int printlevel = 0;
00538
00539 try
00540 {
00541
00542 if(osoption == NULL && osol.length() > 0)
00543 {
00544 m_osolreader = new OSoLReader();
00545 osoption = m_osolreader->readOSoL( osol);
00546 }
00547
00548 if( osoption != NULL && osoption->getNumberOfSolverOptions() > 0 )
00549 {
00550 #ifndef NDEBUG
00551 outStr.str("");
00552 outStr.clear();
00553 outStr << "number of solver options ";
00554 outStr << osoption->getNumberOfSolverOptions();
00555 outStr << std::endl;
00556 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_debug, outStr.str());
00557 #endif
00558
00559 std::vector<SolverOption*> optionsVector;
00560 optionsVector = osoption->getSolverOptions( "csdp",true);
00561 char *pEnd;
00562 int i;
00563 int num_ipopt_options = optionsVector.size();
00564 for(i = 0; i < num_ipopt_options; i++)
00565 {
00566 #ifndef NDEBUG
00567 outStr.str("");
00568 outStr.clear();
00569 outStr << "csdp solver option ";
00570 outStr << optionsVector[ i]->name;
00571 outStr << std::endl;
00572 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_trace, outStr.str());
00573 #endif
00574 optStr << optionsVector[ i]->name << "=" << optionsVector[ i]->value << std::endl;
00575 }
00576
00577 FILE *paramfile;
00578 paramfile=fopen("param.csdp","w");
00579 if (!paramfile)
00580 throw ErrorClass("File open error during option initialization");
00581
00582 fprintf(paramfile,"%s",(optStr.str()).c_str());
00583 fclose(paramfile);
00584 }
00585 bSetSolverOptions = true;
00586 return;
00587 }
00588 catch(const ErrorClass& eclass)
00589 {
00590 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_debug,
00591 "Error in setSolverOption\n");
00592 osresult->setGeneralMessage( eclass.errormsg);
00593 osresult->setGeneralStatusType( "error");
00594 osrl = osrlwriter->writeOSrL( osresult);
00595 throw ErrorClass( osrl);
00596 }
00597 }
00598
00599
00600 #if 0
00601 void CsdpSolver::setInitialValues() throw (ErrorClass)
00602 {
00603 std::ostringstream outStr;
00604 try
00605 {
00606 if(osinstance->getObjectiveNumber() <= 0)
00607 throw ErrorClass("Ipopt NEEDS AN OBJECTIVE FUNCTION\n(For pure feasibility problems, use zero function.)");
00608 this->bSetSolverOptions = true;
00609
00610
00611 app->Options()->SetIntegerValue("print_level", 0);
00612 app->Options()->SetIntegerValue("max_iter", 20000);
00613 app->Options()->SetNumericValue("bound_relax_factor", 0, true, true);
00614 app->Options()->SetStringValue("mu_strategy", "adaptive", true, true);
00615
00616 app->Options()->SetStringValue("check_derivatives_for_naninf", "yes");
00617
00618 if( (osinstance->getNumberOfNonlinearExpressions() <= 0) &&
00619 (osinstance->getNumberOfQuadraticTerms() <= 0) )
00620 {
00621 app->Options()->SetStringValue("hessian_constant", "yes", true, true);
00622 }
00623 if(osinstance->getObjectiveNumber() > 0)
00624 {
00625 if( osinstance->instanceData->objectives->obj[ 0]->maxOrMin.compare("min") != 0)
00626 {
00627 app->Options()->SetStringValue("nlp_scaling_method", "user-scaling");
00628 }
00629 }
00630
00631
00632
00633 if(osoption == NULL && osol.length() > 0)
00634 {
00635 m_osolreader = new OSoLReader();
00636 osoption = m_osolreader->readOSoL( osol);
00637 }
00638
00639 if( osoption != NULL && osoption->getNumberOfSolverOptions() > 0 )
00640 {
00641 #ifndef NDEBUG
00642 outStr.str("");
00643 outStr.clear();
00644 outStr << "number of solver options ";
00645 outStr << osoption->getNumberOfSolverOptions();
00646 outStr << std::endl;
00647 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_debug, outStr.str());
00648 #endif
00649 std::vector<SolverOption*> optionsVector;
00650 optionsVector = osoption->getSolverOptions( "ipopt",true);
00651 char *pEnd;
00652 int i;
00653 int num_ipopt_options = optionsVector.size();
00654 for(i = 0; i < num_ipopt_options; i++)
00655 {
00656 #ifndef NDEBUG
00657 outStr.str("");
00658 outStr.clear();
00659 outStr << "ipopt solver option ";
00660 outStr << optionsVector[ i]->name;
00661 outStr << std::endl;
00662 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_trace, outStr.str());
00663 #endif
00664 if(optionsVector[ i]->type == "numeric" )
00665 {
00666 #ifndef NDEBUG
00667 outStr.str("");
00668 outStr.clear();
00669 outStr << "FOUND A NUMERIC OPTION ";
00670 outStr << os_strtod( optionsVector[ i]->value.c_str(), &pEnd );
00671 outStr << std::endl;
00672 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_trace, outStr.str());
00673 #endif
00674 app->Options()->SetNumericValue(optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
00675 }
00676 else if(optionsVector[ i]->type == "integer" )
00677 {
00678 #ifndef NDEBUG
00679 outStr.str("");
00680 outStr.clear();
00681 outStr << "FOUND AN INTEGER OPTION ";
00682 outStr << atoi( optionsVector[ i]->value.c_str() );
00683 outStr << std::endl;
00684 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_trace, outStr.str());
00685 #endif
00686 app->Options()->SetIntegerValue(optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ) );
00687 }
00688 else if(optionsVector[ i]->type == "string" )
00689 {
00690 #ifndef NDEBUG
00691 outStr.str("");
00692 outStr.clear();
00693 outStr << "FOUND A STRING OPTION ";
00694 outStr << optionsVector[ i]->value.c_str();
00695 outStr << std::endl;
00696 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_trace, outStr.str());
00697 #endif
00698 app->Options()->SetStringValue(optionsVector[ i]->name, optionsVector[ i]->value);
00699 }
00700 }
00701 }
00702 return;
00703 }
00704 catch(const ErrorClass& eclass)
00705 {
00706 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_error, "Error while setting options in IpoptSolver\n");
00707 osresult->setGeneralMessage( eclass.errormsg);
00708 osresult->setGeneralStatusType( "error");
00709 osrl = osrlwriter->writeOSrL( osresult);
00710 throw ErrorClass( osrl) ;
00711 }
00712 }
00713
00714 #endif
00715
00716
00717 void CsdpSolver::solve() throw (ErrorClass)
00718 {
00719 std::ostringstream outStr;
00720
00721 if( this->bCallbuildSolverInstance == false) buildSolverInstance();
00722 if( this->bSetSolverOptions == false) setSolverOptions();
00723 try
00724 {
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735 initsoln(nC_rows,ncon,C_matrix,rhsValues,mconstraints,&X,&y,&Z);
00736
00737
00738
00739
00740
00741 int returnCode = easy_sdp(nC_rows,ncon,C_matrix,rhsValues,mconstraints,0.0,&X,&y,&Z,&pobj,&dobj);
00742
00743 double* mdObjValues = NULL;
00744 int solIdx = 0;
00745 int numberOfOtherVariableResults;
00746 int otherIdx;
00747 int numCon = osinstance->getConstraintNumber();
00748
00749 if(osinstance->getObjectiveNumber() > 0)
00750 {
00751 mdObjValues = new double[1];
00752 mdObjValues[0] = (dobj+pobj)/2;
00753 outStr << std::endl << "Objective value f(x*) = " << os_dtoa_format(mdObjValues[0]);
00754 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_summary, outStr.str());
00755 }
00756
00757 std::string message = "Csdp solver finishes to the end.";
00758 std::string solutionDescription = "";
00759
00760
00761 if(osresult->setSolverInvoked( "COIN-OR Csdp") != true)
00762 throw ErrorClass("OSResult error: setSolverInvoked");
00763 if(osresult->setServiceName( OSgetVersionInfo()) != true)
00764 throw ErrorClass("OSResult error: setServiceName");
00765 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
00766 throw ErrorClass("OSResult error: setInstanceName");
00767
00768
00769
00770
00771
00772 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00773 throw ErrorClass("OSResult error: setVariableNumer");
00774
00775 if(osresult->setObjectiveNumber( 1) != true)
00776 throw ErrorClass("OSResult error: setObjectiveNumber");
00777 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00778 throw ErrorClass("OSResult error: setConstraintNumber");
00779 if(osresult->setSolutionNumber( 1) != true)
00780 throw ErrorClass("OSResult error: setSolutionNumer");
00781 if(osresult->setGeneralMessage( message) != true)
00782 throw ErrorClass("OSResult error: setGeneralMessage");
00783
00784
00785 switch( returnCode)
00786 {
00787 case 0:
00788 case 3:
00789 {
00790 if (returnCode == 0)
00791 {
00792 solutionDescription = "SUCCESS[Csdp]: Algorithm terminated normally at an optimal point, satisfying the convergence tolerances.";
00793 osresult->setSolutionStatus(solIdx, "optimal", solutionDescription);
00794 }
00795 else
00796 {
00797 solutionDescription = "PARTIAL SUCCESS[Csdp]: A solution has been found, but full accuracy was not achieved.";
00798 osresult->setSolutionStatus(solIdx, "unsure", solutionDescription);
00799 }
00800
00801 if (osinstance->getObjectiveNumber() > 0)
00802 osresult->setObjectiveValuesDense(solIdx, mdObjValues);
00803
00804 if(numCon > 0)
00805 osresult->setDualVariableValuesDense(solIdx, y+1);
00806
00807 int* colOffset = new int[X.nblocks+1];
00808 colOffset[0] = 0;
00809 for (int i=1; i<=X.nblocks; i++)
00810 colOffset[i] = colOffset[i-1] + X.blocks[i].blocksize;
00811
00812 int* colOffsetD = new int[Z.nblocks+1];
00813 colOffsetD[0] = 0;
00814 for (int i=1; i<=Z.nblocks; i++)
00815 colOffsetD[i] = colOffsetD[i-1] + Z.blocks[i].blocksize;
00816
00817
00818 if (!osresult->setMatrixVariableSolution(0,1,1))
00819 throw ErrorClass("OSResult error: setMatrixVariableSolution");
00820
00821
00822 if (!osresult->setMatrixVarValuesAttributes(0,0,0,colOffset[X.nblocks],
00823 colOffset[X.nblocks], ENUM_MATRIX_SYMMETRY_lower))
00824 throw ErrorClass("OSResult error: setMatrixVarValuesAttributes");
00825
00826 if (!osresult->setMatrixVariablesOtherResultGeneralAttributes(0, 0, "dual matrix",
00827 "", "", "", "csdp", "", 1))
00828 throw ErrorClass("OSResult error: setMatrixVariablesOtherResultGeneralAttributes");
00829 if (!osresult->setMatrixVariablesOtherResultMatrixAttributes(0, 0, 0,
00830 colOffset[Z.nblocks],colOffset[Z.nblocks], ENUM_MATRIX_SYMMETRY_lower))
00831 throw ErrorClass("OSResult error: setMatrixVariablesOtherResultMatrixAttributes");
00832
00833 if (!osresult->setMatrixVarValuesBlockStructure(0, 0, colOffset, X.nblocks + 1,
00834 colOffset, X.nblocks + 1, X.nblocks))
00835 throw ErrorClass("OSResult error: setMatrixVarValuesBlockStructure");
00836
00837 if (!osresult->setMatrixVariablesOtherResultBlockStructure(0, 0, 0, colOffsetD, Z.nblocks + 1,
00838 colOffsetD, Z.nblocks + 1, Z.nblocks))
00839 throw ErrorClass("OSResult error: setMatrixVariablesOtherResultBlockStructure");
00840
00841 int* start;
00842 int* index;
00843 ConstantMatrixValues* value;
00844
00845 int nonz;
00846 double ent;
00847
00848
00849 for (int blk=1; blk<=X.nblocks; blk++)
00850 {
00851 start = new int[colOffset[blk]-colOffset[blk-1]+1];
00852 start[0] = 0;
00853 nonz = 0;
00854
00855 switch (X.blocks[blk].blockcategory)
00856 {
00857 case DIAG:
00858 for (int i=1; i<=X.blocks[blk].blocksize; i++)
00859 {
00860 ent=X.blocks[blk].data.vec[i];
00861 if (ent != 0.0)
00862 nonz++;
00863 start[i] = nonz;
00864 };
00865 break;
00866 case MATRIX:
00867 for (int i=1; i<=X.blocks[blk].blocksize; i++)
00868 {
00869 for (int j=i; j<=X.blocks[blk].blocksize; j++)
00870 {
00871 ent=X.blocks[blk].data.mat[ijtok(i,j,X.blocks[blk].blocksize)];
00872 if (ent != 0.0)
00873 nonz++;
00874 };
00875 start[i] = nonz;
00876 };
00877 break;
00878 case PACKEDMATRIX:
00879 default:
00880 throw ErrorClass("Invalid Block Type in CSDP solution");
00881 };
00882
00883
00884 index = new int[nonz];
00885 value = new ConstantMatrixValues();
00886 value->numberOfEl = nonz;
00887 value->el = new double[nonz];
00888
00889 nonz = 0;
00890 switch (X.blocks[blk].blockcategory)
00891 {
00892 case DIAG:
00893 for (int i=1; i<=X.blocks[blk].blocksize; i++)
00894 {
00895 ent=X.blocks[blk].data.vec[i];
00896 if (ent != 0.0)
00897 {
00898 index[nonz] = i-1;
00899 value->el[nonz] = ent;
00900 nonz++;
00901 }
00902 };
00903 break;
00904 case MATRIX:
00905 for (int i=1; i<=X.blocks[blk].blocksize; i++)
00906 {
00907 for (int j=i; j<=X.blocks[blk].blocksize; j++)
00908 {
00909 ent=X.blocks[blk].data.mat[ijtok(i,j,X.blocks[blk].blocksize)];
00910 if (ent != 0.0)
00911 {
00912 index[nonz] = j-1;
00913 value->el[nonz] = ent;
00914 nonz++;
00915 }
00916 };
00917 start[i] = nonz;
00918 };
00919 break;
00920 case PACKEDMATRIX:
00921 default:
00922 throw ErrorClass("Invalid Block Type in CSDP solution");
00923 };
00924
00925
00926 if (!osresult->setMatrixVarValuesBlockElements(0, 0, blk-1, blk-1, blk-1, nonz,
00927 start, index, value,
00928 ENUM_MATRIX_TYPE_constant,
00929 ENUM_MATRIX_SYMMETRY_lower))
00930 throw ErrorClass("OSResult error: setMatrixVarValuesBlockElements");
00931 };
00932
00933
00934 for (int blk=1; blk<=Z.nblocks; blk++)
00935 {
00936 start = new int[colOffsetD[blk]-colOffsetD[blk-1]+1];
00937 start[0] = 0;
00938 nonz = 0;
00939
00940 switch (Z.blocks[blk].blockcategory)
00941 {
00942 case DIAG:
00943 for (int i=1; i<=Z.blocks[blk].blocksize; i++)
00944 {
00945 ent=Z.blocks[blk].data.vec[i];
00946 if (ent != 0.0)
00947 nonz++;
00948 start[i] = nonz;
00949 };
00950
00951 break;
00952 case MATRIX:
00953 for (int i=1; i<=Z.blocks[blk].blocksize; i++)
00954 {
00955 for (int j=i; j<=Z.blocks[blk].blocksize; j++)
00956 {
00957 ent=Z.blocks[blk].data.mat[ijtok(i,j,Z.blocks[blk].blocksize)];
00958 if (ent != 0.0)
00959 nonz++;
00960 };
00961 start[i] = nonz;
00962 };
00963 break;
00964 case PACKEDMATRIX:
00965 default:
00966 throw ErrorClass("Invalid Block Type in CSDP solution");
00967 };
00968
00969
00970 index = new int[nonz];
00971 value = new ConstantMatrixValues();
00972 value->numberOfEl = nonz;
00973 value->el = new double[nonz];
00974
00975 nonz = 0;
00976 switch (Z.blocks[blk].blockcategory)
00977 {
00978 case DIAG:
00979 for (int i=1; i<=Z.blocks[blk].blocksize; i++)
00980 {
00981 ent=Z.blocks[blk].data.vec[i];
00982 if (ent != 0.0)
00983 {
00984 index[nonz] = i-1;
00985 value->el[nonz] = ent;
00986 nonz++;
00987 }
00988 };
00989 break;
00990 case MATRIX:
00991 for (int i=1; i<=Z.blocks[blk].blocksize; i++)
00992 {
00993 for (int j=i; j<=Z.blocks[blk].blocksize; j++)
00994 {
00995 ent=Z.blocks[blk].data.mat[ijtok(i,j,Z.blocks[blk].blocksize)];
00996 if (ent != 0.0)
00997 {
00998 index[nonz] = j-1;
00999 value->el[nonz] = ent;
01000 nonz++;
01001 }
01002 };
01003 start[i] = nonz;
01004 };
01005 break;
01006 case PACKEDMATRIX:
01007 default:
01008 throw ErrorClass("Invalid Block Type in CSDP solution");
01009 };
01010
01011 if (!osresult->setMatrixVariablesOtherResultBlockElements(0, 0, 0, blk-1, blk-1, blk-1,
01012 nonz, start, index, value,
01013 ENUM_MATRIX_TYPE_constant,
01014 ENUM_MATRIX_SYMMETRY_lower))
01015 throw ErrorClass("OSResult error: setMatrixVariablesOtherResultBlockElements");
01016 };
01017 break;
01018 }
01019 case 1:
01020 solutionDescription = "PRIMAL_INFEASIBILITY[Csdp]: Problem is primal infeasible.";
01021 osresult->setSolutionStatus(solIdx, "infeasible", solutionDescription);
01022 break;
01023
01024 case 2:
01025 solutionDescription = "DUAL_INFEASIBILITY[Csdp]: Problem is dual infeasible.";
01026 osresult->setSolutionStatus(solIdx, "infeasible", solutionDescription);
01027 break;
01028
01029 case 4:
01030 solutionDescription = "MAXITER_EXCEEDED[Csdp]: Maximum number of iterations exceeded.";
01031 osresult->setSolutionStatus(solIdx, "stoppedByLimit", solutionDescription);
01032 break;
01033
01034 case 5:
01035 solutionDescription = "STUCK AT EDGE[Csdp]: Stuck at edge of primal infeasibility.";
01036 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
01037 break;
01038
01039 case 6:
01040 solutionDescription = "STUCK AT EDGE[Csdp]: Stuck at edge of dual infeasibility.";
01041 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
01042 break;
01043
01044 case 7:
01045 solutionDescription = "LACK OF PROGRESS[Csdp]: Stopped due to lack of progress.";
01046 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
01047 break;
01048
01049 case 8:
01050 solutionDescription = "SINGULARITY DETECTED[Csdp]: X, Z or O was singular.";
01051 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
01052 break;
01053
01054 case 9:
01055 solutionDescription = "NaN or INF[Csdp]: Detected NaN or Infinity during computations.";
01056 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
01057 break;
01058 }
01059
01060 if (returnCode != 0)
01061 throw ErrorClass("Csdp FAILED TO SOLVE THE PROBLEM");
01062
01063 osrl = osrlwriter->writeOSrL( osresult);
01064 }
01065
01066 catch (const ErrorClass& eclass)
01067 {
01068 outStr.str("");
01069 outStr.clear();
01070 outStr << "error in OSCsdpSolver routine solve():\n" << eclass.errormsg << endl;
01071 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_error, outStr.str());
01072
01073 osresult->setGeneralMessage( eclass.errormsg);
01074 osresult->setGeneralStatusType( "error");
01075 osrl = osrlwriter->writeOSrL( osresult);
01076 throw ErrorClass( osrl) ;
01077 }
01078 }
01079
01080 void CsdpSolver::dataEchoCheck()
01081 {
01082 int i0, j0, blk0;
01083 struct sparseblock *pp;
01084 std::ostringstream outStr;
01085
01086 outStr << std::endl << "Check problem data:" << std::endl << std::endl;
01087
01088 outStr << "Dimension of matrices (number of rows): n=" << nC_rows << std::endl;
01089 outStr << "Number of constraints (and matrices A_i): k=" << ncon << std::endl;
01090 for (i0=1; i0 <= ncon; i0++)
01091 {
01092 outStr << std::endl << "Right-hand side of constraint " << i0 << ": "
01093 << rhsValues[i0] << std::endl;
01094 outStr << std::endl << "Data for matrix A_" << i0 << ":" << std::endl;
01095 pp = mconstraints[i0].blocks;
01096 while (pp != NULL)
01097 {
01098 outStr << std::endl << "Block " << pp->blocknum << ":" << std::endl;;
01099 outStr << "Block size: " << pp->blocksize << std::endl;
01100 outStr << "Number of entries: " << pp->numentries << std::endl;
01101 for (j0=1; j0 <= pp->numentries; j0++)
01102 outStr << "Entry in row " << pp->iindices[j0] << ", col " << pp->jindices[j0]
01103 << " has value " << pp->entries[j0] << std::endl;
01104 pp = pp->next;
01105 }
01106 }
01107
01108 outStr << std::endl << "Data for matrix C:" << std::endl;
01109 outStr << "Number of blocks: " << C_matrix.nblocks << std::endl;
01110 for (blk0=1; blk0 <= C_matrix.nblocks; blk0++)
01111 {
01112 outStr << std::endl << "Data for block " << blk0 << ":" << std::endl;
01113 outStr << "Size: " << C_matrix.blocks[blk0].blocksize << std::endl;
01114 if (C_matrix.blocks[blk0].blockcategory == DIAG)
01115 {
01116 outStr << "Type: diagonal" << std::endl;
01117 for (i0=1; i0 <= C_matrix.blocks[blk0].blocksize; i0++)
01118 outStr << "Entry in row " << i0 << ", col " << i0 << " has value "
01119 << C_matrix.blocks[blk0].data.vec[i0] << std::endl;
01120 }
01121 else
01122 {
01123 outStr << "Type: dense" << std::endl;
01124 for (i0=1; i0 <= C_matrix.blocks[blk0].blocksize; i0++)
01125 for (j0=1; j0 <= C_matrix.blocks[blk0].blocksize; j0++)
01126 outStr << "Entry in row " << i0 << ", col " << j0 << " has value "
01127 << C_matrix.blocks[blk0].data.mat[ijtok(i0,j0,C_matrix.blocks[blk0].blocksize)]
01128 << std::endl;
01129 }
01130 }
01131 osoutput->OSPrint(ENUM_OUTPUT_AREA_OSSolverInterfaces, ENUM_OUTPUT_LEVEL_debug, outStr.str());
01132 }
01133
01134