/* ------------------------------------------------------------- This file is a component of SDPA Copyright (C) 2004-2013 SDPA Project This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------- */ #include "sdpa_io.h" #include "sdpa_linear.h" #include #include namespace sdpa { void IO::read(FILE* fpData, FILE* fpout, int& m, char* str) { while (true) { volatile int dummy=0; dummy++;//for gcc-3.3 bug fgets(str,lengthOfString,fpData); if (str[0]=='*' || str[0]=='"') { fprintf(fpout,"%s",str); } else { sscanf(str,"%d",&m); break; } } } void IO::read(FILE* fpData, int & nBlock) { fscanf(fpData,"%d",&nBlock); } void IO::read(FILE* fpData, BlockStruct& bs) { for (int l=0; l 0 ) { bs.blockType[l] = BlockStruct::btSDP; } if (bs.blockStruct[l] < 0 ) { bs.blockType[l] = BlockStruct::btLP; } } } void IO::read(FILE* fpData, Vector& b) { for (int k=0; k 0) { // if y[0] locates the first charcter in fpData // then we need the following line yVec.ele[k] = -tmp; // rMessage("yVec.ele[" << k << "] = " << -tmp); k++; } for (; k* readData; NewArray(readData, vector, m+1); while (true) { lineNumber++; if (fscanf(fpData,"%*[^0-9+-]%d",&k)<=0) { break; } if (fscanf(fpData,"%*[^0-9+-]%d",&l)<=0) { break; } if (fscanf(fpData,"%*[^0-9+-]%d",&i)<=0) { break; } if (fscanf(fpData,"%*[^0-9+-]%d",&j)<=0) { break; } if (fscanf(fpData,"%*[^0-9+-]%lf",&value)<=0) { break; } #if 0 rMessage("Data " << k << "," << l << "," << i << "," << j << "," << value); #endif IO::LIJV* oneData; NewArray(oneData, IO::LIJV, 1); oneData[0].SDPl = -1; // -1 means empty here oneData[0].LPl = -1; oneData[0].i = i-1; oneData[0].j = j-1; oneData[0].value = value; if (bs.blockType[l-1] == BlockStruct::btSDP) { int l2 = bs.blockNumber[l-1]; oneData[0].SDPl = l2; readData[k].push_back(oneData); } else if (bs.blockType[l-1] == BlockStruct::btLP) { if (i!=j) { printf("******** invalid data line %d, %d, %d, %d, %e ***\n", k,l,i,j,value); printf("Line number [%d] in 5-element-lines is invalid\n", lineNumber); printf("Check your input file\n"); printf("Note: -1000 may appear in the above invalid report line if the corresponding place is not read correctly.\n"); rError("IO::initializeLinearSpace"); } int l2 = bs.blockNumber[l-1]; oneData[0].LPl = l2+i-1; readData[k].push_back(oneData); } else { printf("******** invalid data line %d, %d, %d, %d, %e ***\n", k,l,i,j,value); printf("Line number [%d] in 5-element-lines is invalid\n", lineNumber); printf("Check your input file\n"); printf("Note: -1000 may appear in the above invalid report line if the corresponding place is not read correctly.\n"); rError("io::read not valid blockType"); } }// end of 'while (true)' vector LP_blockCount; vector SDP_blockCount; for (int k=0; k= 0) { LP_blockCount.push_back(oneData[0].LPl); } if (oneData[0].SDPl >= 0) { SDP_blockCount.push_back(oneData[0].SDPl); } } sort(LP_blockCount.begin(), LP_blockCount.end()); sort(SDP_blockCount.begin(), SDP_blockCount.end()); int LP_sp_nBlock = 0; int SDP_sp_nBlock = 0; int LP_old_block = -1; int SDP_old_block = -1; const int LP_length = LP_blockCount.size(); const int SDP_length = SDP_blockCount.size(); for (int index1 = 0; index1 < LP_length; ++index1) { if (LP_blockCount[index1] != LP_old_block) { LP_old_block = LP_blockCount[index1]; LP_sp_nBlock++; } } for (int index1 = 0; index1 < SDP_length; ++index1) { if (SDP_blockCount[index1] != SDP_old_block) { SDP_old_block = SDP_blockCount[index1]; SDP_sp_nBlock++; } } CompSpace* target = &inputData.C; if (k>0) { target = &inputData.A[k-1]; } target->initialize(LP_sp_nBlock, SDP_sp_nBlock); int index_t = 0; LP_old_block = -1; for (int index1 = 0; index1 < LP_length; ++index1) { const int current_block = LP_blockCount[index1]; if (current_block != LP_old_block) { target->LP_sp_index[index_t] = current_block; LP_old_block = current_block; index_t++; } } index_t = 0; SDP_old_block = -1; for (int index1 = 0; index1 < SDP_length; ++index1) { const int current_block = SDP_blockCount[index1]; if (current_block != SDP_old_block) { target->SDP_sp_index[index_t] = current_block; SDP_old_block = current_block; target->SDP_sp_block[index_t].nRow = bs.SDP_blockStruct[current_block]; target->SDP_sp_block[index_t].nCol = bs.SDP_blockStruct[current_block]; index_t++; } } #if 0 rMessage("LP blocks = "); for (int index2 = 0; index2 < LP_sp_nBlock; ++index2) { printf(" %d", target->LP_sp_index[index2]); } printf("\n"); rMessage("SDP blocks = "); for (int index2 = 0; index2 < SDP_sp_nBlock; ++index2) { printf(" %d", target->SDP_sp_index[index2]); } printf("\n"); #endif target->initializeInputVector(); } LP_blockCount.clear(); SDP_blockCount.clear(); for (int k=0; k0) { target = &inputData.A[k-1]; scale = 1.0; } int length = readData[k].size(); for (int index1 = 0; index1 < length; ++index1) { IO::LIJV* oneData = readData[k].at(index1); if (oneData[0].LPl >= 0) { target->setElement_LP(oneData[0].LPl, oneData[0].value*scale); } if (oneData[0].SDPl >= 0) { target->setElement_SDP(oneData[0].SDPl, oneData[0].i, oneData[0].j, oneData[0].value*scale); } DeleteArray(oneData); } } DeleteArray(readData); double v1 = 0; // dummy initialize double v2 = 0; // dummy initialize inputData.C.sortInputVector(); inputData.C.checkInputDataStructure(l, i, j, v1, v2); inputData.C.makeInternalStructure(); if (l>=0) { printf("***** invalid data ******\n"); printf("F[0]:%d-th SDP block:[%d, %d]-th element has more than one input\n", l+1, i+1, j+1); rError("Stop due to input error\n"); } for (int k=0; k=0) { printf("***** invalid data ******\n"); printf("F[%d]:%d-th SDP block:[%d, %d]-th element has more than one input\n", k+1, l+1, i+1, j+1); rError("Stop due to input error\n"); } } #if 0 rMessage("************** Read finished, internal data is from here."); rMessage("C = -------------------------"); inputData.C.display(); for (int k=0; k* SDP_index; NewArray(SDP_index,vector,m+1); vector* SOCP_index; NewArray(SOCP_index,vector,m+1); vector* LP_index; NewArray(LP_index,vector,m+1); // for SDP int SDP_sp_nBlock; int* SDP_sp_index; int* SDP_sp_blockStruct; int* SDP_sp_NonZeroNumber; NewArray(SDP_sp_index,int,bs.SDP_nBlock); NewArray(SDP_sp_blockStruct,int,bs.SDP_nBlock); NewArray(SDP_sp_NonZeroNumber,int,bs.SDP_nBlock); // for SOCP int SOCP_sp_nBlock; int* SOCP_sp_blockStruct; int* SOCP_sp_index; int* SOCP_sp_NonZeroNumber; // for LP int LP_sp_nBlock; int* LP_sp_index; NewArray(LP_sp_index,int,bs.LP_nBlock); if (isDataSparse) { int i,j,k,l; i=j=k=l = -1000; // dummy initialize double value; value = -1000; int lineNumber = 0; while (true) { lineNumber++; if (fscanf(fpData,"%*[^0-9+-]%d",&k)<=0) { break; } if (fscanf(fpData,"%*[^0-9+-]%d",&l)<=0) { break; } if (fscanf(fpData,"%*[^0-9+-]%d",&i)<=0) { break; } if (fscanf(fpData,"%*[^0-9+-]%d",&j)<=0) { break; } if (fscanf(fpData,"%*[^0-9+-]%lf",&value)<=0) { break; } if (bs.blockType[l-1] == BlockStruct::btSDP) { int l2 = bs.blockNumber[l-1]; SDP_index[k].push_back(l2); } else if (bs.blockType[l-1] == BlockStruct::btLP) { if (i!=j){ printf("******** invalid data line %d, %d, %d, %d, %e ***\n", k,l,i,j,value); printf("Line number [%d] in 5-element-lines is invalid\n", lineNumber); printf("Check your input file\n"); printf("Note: -1000 may appear in the above invalid report line if the corresponding place is not read correctly.\n"); rError("IO::initializeLinearSpace"); } int l2 = bs.blockNumber[l-1]; LP_index[k].push_back(l2+i-1); } else { printf("******** invalid data line %d, %d, %d, %d, %e ***\n", k,l,i,j,value); printf("Line number [%d] in 5-element-lines is invalid\n", lineNumber); printf("Check your input file\n"); printf("Note: -1000 may appear in the above invalid report line if the corresponding place is not read correctly.\n"); rError("io::read not valid blockType"); } }// end of 'while (true)' } else { // isDataSparse == false // constant matrix for (int l=0; lncol; for (int j=0; j < ncol; ++j) { const int start_row = ((int*)rD->p)[j]; const int end_row = ((int*)rD->p)[j+1]; for (int i_index = start_row; i_index < end_row; ++i_index) { const int i = (( int*)rD->i)[i_index]; const double value = ((double*)rD->x)[i_index]; if (i==j) { d_norm += value * value; } else { d_norm += 2.0 * value * value; } } } } d_norm = sqrt(d_norm); double x_min = 1.0e+50; double z_min = 1.0e+50; DenseLinearSpace& finalX = currentPt.finalX; DenseLinearSpace& finalZ = currentPt.finalZ; for (int l=0; l < finalX.LP_nBlock; ++l) { if (x_min > finalX.LP_block[l]) { x_min = finalX.LP_block[l]; } } for (int l=0; l < finalZ.LP_nBlock; ++l) { if (z_min > finalZ.LP_block[l]) { z_min = finalZ.LP_block[l]; } } for (int l=0; l < finalX.SDP_nBlock; ++l) { DenseMatrix& xMat = finalX.SDP_block[l]; int nDim = xMat.nRow; DenseMatrix workMatrix; workMatrix.copyFrom(xMat); Vector eigenVec; eigenVec.initialize(nDim); Vector workVec; workVec.initialize(3*nDim-1); Lal::getMinEigenValue(workMatrix, eigenVec, workVec); for (int i=0; i eigenVec.ele[i]) { x_min = eigenVec.ele[i]; } } } for (int l=0; l < finalZ.SDP_nBlock; ++l) { DenseMatrix& zMat = finalZ.SDP_block[l]; int nDim = zMat.nRow; DenseMatrix workMatrix; workMatrix.copyFrom(zMat); Vector eigenVec; eigenVec.initialize(nDim); Vector workVec; workVec.initialize(3*nDim-1); Lal::getMinEigenValue(workMatrix, eigenVec, workVec); for (int i=0; i eigenVec.ele[i]) { z_min = eigenVec.ele[i]; } } } #if 0 printf("b1:%e\n",b1); printf("c1:%e\n",c1); printf("p_norm:%e\n",p_norm); printf("d_norm:%e\n",d_norm); printf("x_min:%e\n",x_min); printf("z_min:%e\n",z_min); #endif double ctx = solveInfo.objValPrimal; double bty = solveInfo.objValDual; double xtz = 0.0; Lal::let(xtz,'=',currentPt.finalX,'.',currentPt.finalZ); for (int i=0; i<=6; ++i) { dimacs_error[i] = 0.0; } rMessage("x_min, z_min"); printf("x_min = %.2e, z_min = %.2e\n", x_min, z_min); dimacs_error[1] = p_norm / (1+b1); dimacs_error[2] = max( 0.0, - x_min / (1+b1)); dimacs_error[3] = d_norm / (1+c1); dimacs_error[4] = max( 0.0, - z_min / (1+c1)); dimacs_error[5] = (ctx - bty) / (1 + fabs(ctx) + fabs(bty)); dimacs_error[6] = xtz / (1 + fabs(ctx) + fabs(bty)); } void IO::printDimacs(double* DimacsError,char* printFormat, FILE* fpout) { if (fpout == NULL) { return; } fprintf(fpout, "\n"); fprintf(fpout, "* DIMACS_ERRORS * \n"); fprintf(fpout, "err1 = "); fprintf(fpout, printFormat, DimacsError[1]); fprintf(fpout, " [||Ax-b|| / (1+||b||_1)]\n"); fprintf(fpout, "err2 = "); fprintf(fpout, printFormat, DimacsError[2]); fprintf(fpout, " [max(0, -lambda(x)/(1+||b||_1))]\n"); fprintf(fpout, "err3 = "); fprintf(fpout, printFormat, DimacsError[3]); fprintf(fpout, " [||A^Ty + z - c || / (1+||c||_1)]\n"); fprintf(fpout, "err4 = "); fprintf(fpout, printFormat, DimacsError[4]); fprintf(fpout, " [max(0, -lambda(z)/(1+||c||_1))]\n"); fprintf(fpout, "err5 = "); fprintf(fpout, printFormat, DimacsError[5]); fprintf(fpout, " [( - ) / (1 + || + ||)]\n"); fprintf(fpout, "err6 = "); fprintf(fpout, printFormat, DimacsError[6]); fprintf(fpout, " [ / (1 + || + ||)]\n"); fprintf(fpout, "\n"); } bool IO::judgeXmake(Parameter& param) { #if REVERSE_PRIMAL_DUAL if (strcmp(param.YPrint,NO_P_FORMAT) == 0) { return false; } #else if (strcmp(param.XPrint,NO_P_FORMAT) == 0) { return false; } #endif return true; } bool IO::judgeZmake(Parameter& param) { #if REVERSE_PRIMAL_DUAL if (strcmp(param.XPrint,NO_P_FORMAT) == 0) { return false; } #else if (strcmp(param.YPrint,NO_P_FORMAT) == 0) { return false; } #endif return true; } void IO::printSolution(BlockStruct& bs, Solutions& currentPt, Parameter& param, FILE* fpout, bool Xmake, bool Zmake) { if (fpout != NULL) { #if REVERSE_PRIMAL_DUAL fprintf(fpout,"xVec = \n"); currentPt.cholmodSpace.yVec.display(fpout,1.0,param.xPrint); fprintf(fpout,"xMat = \n"); currentPt.finalZ.displaySolution(bs,fpout,param.XPrint); fprintf(fpout,"yMat = \n"); currentPt.finalX.displaySolution(bs,fpout,param.YPrint); #else fprintf(fpout,"xMat = \n"); currentPt.finalX.displaySolution(bs,fpout,param.XPrint); fprintf(fpout,"yVec = \n"); currentPt.cholmodSpace.yVec.display(fpout,1.0,param.xPrint); fprintf(fpout,"zMat = \n"); currentPt.finalZ.displaySolution(bs,fpout,param.YPrint); #endif } } } // end of namespace 'sdpa'