/* * Read in a problem in SDPpack SQLP format, and convert it to SDPA sparse * format. * * Usage: * * sqlptosdpa * */ #include #include #include /* Declarations needed to handle indexing into Fortran arrays. */ /* First, to convert fortran i,j indices into a C vector index. */ #define ijtok(iiii,jjjj,lda) ((jjjj-1)*lda+iiii-1) /* Next, to convert C vector index into Fortran i,j indices. */ #define ktoi(k,lda) ((k % lda)+1) #define ktoj(k,lda) ((k/lda)+1) int main(argc,argv) int argc; char *argv[]; { FILE *fid; int orig_constraints; int *sdp_block_sizes; int sdp_blocks; int q_blocks; int *q_block_sizes=NULL; int l_vars; int l_blocks=0; int q_vars; int block_size; int i; int j=0; int k; int kk; int p; int base; int block_type; int num_entries; double foo; int indexi; int indexj; int ret; int *entry_counts; int cs_entries=0; int aq_entries=0; int al_entries=0; int extra_constraints=0; double *b; int *AQi; int *AQj; double *AQ; int *CSi; int *CSj; double *CS; int *CSblock; double *CL; int *ALi; int *ALj; double *AL; double *CQ; typedef double *dptr; typedef int *iptr; dptr *AS; iptr *ASi; iptr *ASj; iptr *ASblock; int *thisASi; int *thisASj; double *thisAS; int *thisASblock; int *which_q_block=NULL; int *q_block_offset=NULL; /* * Check that we have enough arguments. */ if (argc != 3) { printf("Usage: \n"); printf("\n"); printf("sqlptosdpa \n"); exit(1); }; /* * Determine the size of the problem. * Return: * orig_constraints * sdp_blocks * sdp_block_sizes * q_blocks * q_block_sizes * l_vars * cs_entries. (Entries in C.S matrix.) * entry_counts (1..m) (Entries in the A.S matrices.) * aq_entries (Entries in the A.Q matrix) * al_entries (Entries in the A.L matrix) */ /* * Open up the SQLP file for reading. */ fid=fopen(argv[1],"r"); if (fid == (FILE *) NULL) { printf("Couldn't open SQLP problem file for reading! \n"); exit(1); }; /* * Read in the count of constraints. */ fscanf(fid,"%d",&orig_constraints); /* * Allocate storage for an array that lists how many entries are in * each A.S array. */ entry_counts=(int *) malloc((orig_constraints+1)*sizeof(int)); for (i=1; i<=orig_constraints; i++) entry_counts[i]=0; /* * Next, read in the constraint rhs's. */ for (i=1; i<=orig_constraints; i++) { ret=fscanf(fid,"%lf",&foo); if (ret != 1) { printf("Incorrect SDPpack file. \n"); exit(1); }; }; /* * Read in the number of sdp blocks. */ ret=fscanf(fid,"%d",&sdp_blocks); if (ret != 1) { printf("Incorrect SDPpack file. \n"); exit(1); }; sdp_block_sizes=(int *) malloc((sdp_blocks+1)*sizeof(int)); if (sdp_blocks != 0) { /* * Next, read in the SDP block sizes. */ for (i=1; i<=sdp_blocks; i++) { ret=fscanf(fid,"%d",&block_size); if (ret != 1) { printf("Incorrect SDPpack file. \n"); exit(1); }; sdp_block_sizes[i]=block_size; }; /* * Next, read over C.S */ for (k=1; k<=sdp_blocks; k++) { ret=fscanf(fid,"%d",&block_type); if (ret != 1) { printf("Incorrect SDPpack file. \n"); exit(1); }; if (block_type == 0) { /* * Read in a dense block. */ block_size=sdp_block_sizes[k]; for (i=1; i<=(block_size*(block_size+1))/2; i++) { fscanf(fid,"%lf",&foo); }; cs_entries=cs_entries+(block_size*(block_size+1))/2; } else { if (block_type == 1) { /* * Read in a sparse block. */ ret=fscanf(fid,"%d",&num_entries); for (i=1; i<=num_entries; i++) { fscanf(fid,"%d",&indexi); fscanf(fid,"%d",&indexj); fscanf(fid,"%lf",&foo); cs_entries++; }; } else { printf("Incorrect SDPpack file. \n"); printf("Bad Block Type. \n"); exit(1); }; }; }; /* End of loop through blocks of Cs */ /* * Now, read through the A.S constraint matrices. */ for (kk=1; kk<= orig_constraints; kk++) { for (k=1; k<=sdp_blocks; k++) { ret=fscanf(fid,"%d",&block_type); if (ret != 1) { printf("Incorrect SDPpack file. \n"); exit(1); }; if (block_type == 0) { /* * Read in a dense block. */ block_size=sdp_block_sizes[k]; for (i=1; i<=(block_size*(block_size+1))/2; i++) { fscanf(fid,"%lf",&foo); }; entry_counts[kk] += (block_size*(block_size+1))/2; } else { if (block_type == 1) { /* * Read in a sparse block. */ ret=fscanf(fid,"%d",&num_entries); for (i=1; i<=num_entries; i++) { fscanf(fid,"%d",&indexi); fscanf(fid,"%d",&indexj); fscanf(fid,"%lf",&foo); entry_counts[kk]++; }; } else { printf("Incorrect SDPpack file. \n"); printf("Bad Block Type. \n"); exit(1); }; }; }; /* End of loop through blocks of AS */ }; /* End of loop through m constraints. */ } else { /* * Nothing in SDP part of the problem. */ }; /* * Next, read the QC part of the problem. */ ret=fscanf(fid,"%d",&q_blocks); if (ret != 1) { printf("Incorrect SDPpack file. \n"); printf("Bad Block Count. \n"); return(1); }; if (q_blocks != 0) { /* * We've got some QC blocks. */ q_block_sizes=(int *) malloc((q_blocks+1)*sizeof(int)); if (q_block_sizes == NULL) { printf("Storage Allocation Failed. \n"); exit(1); }; /* * Read in the block sizes. */ q_vars=0; for (i=1; i<=q_blocks; i++) { ret=fscanf(fid,"%d",&block_size); if (ret != 1) { printf("Incorrect SDPpack file. \n"); printf("Bad QC Block Size. \n"); return(1); }; q_block_sizes[i]=block_size; q_vars=q_vars+block_size; extra_constraints=extra_constraints+block_size-1; if (block_size > 2) { extra_constraints += ((block_size-2)*(block_size-1))/2; }; }; /* * Compute arrays which_q_block, and q_block_offset. */ which_q_block=(int *)malloc((q_vars+1)*sizeof(int)); q_block_offset=(int *)malloc((q_vars+1)*sizeof(int)); p=1; for (i=1; i<=q_blocks; i++) { for (j=1; j<=q_block_sizes[i]; j++) { which_q_block[p]=i; q_block_offset[p]=j; p++; }; }; /* * Now, read in the cost vector C.q */ for (i=1; i<=q_vars; i++) { ret=fscanf(fid,"%lf",&foo); if (ret != 1) { printf("Incorrect SDPpack file. \n"); printf("Bad C.q entry. \n"); exit(1); }; }; /* * Next, read in the constraint matrix Aq */ ret=fscanf(fid,"%d",&block_type); if (ret != 1) { printf("Incorrect SDPpack file. \n"); printf("Bad AQ block type. \n"); return(1); }; if (block_type == 0) { /* * Read in a dense AQ matrix. */ for (i=1; i<=q_vars*orig_constraints; i++) { ret=fscanf(fid,"%lf",&foo); }; aq_entries=aq_entries+q_vars*orig_constraints; } else { if (block_type == 1) { /* * Read in a sparse AQ matrix. */ ret=fscanf(fid,"%d",&num_entries); for (i=1; i<=num_entries; i++) { fscanf(fid,"%d",&indexi); fscanf(fid,"%d",&indexj); fscanf(fid,"%lf",&foo); aq_entries++; }; } else { printf("Incorrect SDPpack file. \n"); printf("Bad AQ type. \n"); return(1); }; }; } else { /* * No QC blocks! */ q_vars=0; }; /* * And read through the LP part of the problem. */ ret=fscanf(fid,"%d",&l_vars); if (ret != 1) { printf("Incorrect SDPpack file. \n"); printf("Bad linear variable count. (phase I) \n"); return(1); }; if (l_vars != 0) { /* * Put in one block for the linear variables. */ l_blocks=1; /* * Read in C.l */ for (i=1; i<=l_vars; i++) { ret=fscanf(fid,"%lf",&foo); } /* * Read in the matrix A.l */ ret=fscanf(fid,"%d",&block_type); if (ret != 1) { printf("Incorrect SDPpack file. \n"); printf("Bad AL block type. 1\n"); return(1); }; if (block_type == 0) { /* * Read in a dense AL matrix. */ for (i=1; i<=l_vars*orig_constraints; i++) { ret=fscanf(fid,"%lf",&foo); }; al_entries=al_entries+l_vars*orig_constraints; } else { if (block_type == 1) { /* * Read in a sparse AL matrix. */ ret=fscanf(fid,"%d",&num_entries); for (i=1; i<=num_entries; i++) { fscanf(fid,"%d",&indexi); fscanf(fid,"%d",&indexj); fscanf(fid,"%le",&foo); al_entries++; }; } else { printf("Incorrect SDPpack file. \n"); printf("Bad AL type. \n"); return(1); }; }; }; /* * Allocate storage for problem data. * * CS C.s matrix. * AS A.s matrices. * CQ C.q vector. * AQ A.q matrix. * CL C.l vector. * AL A.l matrix. * * All vectors stored as C vectors with 1..n indexing. * All arrays stored in i,j,ent fashion, upper triangles only. * An array of pointers to ASI, ASJ, ASENT arrays. */ b=(double *) malloc((orig_constraints+1)*sizeof(double)); CSi=(int *) malloc((cs_entries+1)*sizeof(int)); if (CSi == NULL) { printf("Storage allocation failed. \n"); exit(1); }; CSj=(int *) malloc((cs_entries+1)*sizeof(int)); if (CSj == NULL) { printf("Storage allocation failed. \n"); exit(1); }; CS=(double *) malloc((cs_entries+1)*sizeof(double)); if (CS == NULL) { printf("Storage allocation failed. \n"); exit(1); }; CSblock=(int *) malloc((cs_entries+1)*sizeof(int)); if (CSblock == NULL) { printf("Storage allocation failed. \n"); exit(1); }; AS=(dptr *) malloc((orig_constraints+1)*sizeof(dptr)); if (AS == NULL) { printf("Storage allocation failed. \n"); exit(1); }; ASi=(iptr *) malloc((orig_constraints+1)*sizeof(iptr)); if (ASi == NULL) { printf("Storage allocation failed. \n"); exit(1); }; ASj=(iptr *) malloc((orig_constraints+1)*sizeof(iptr)); if (ASj == NULL) { printf("Storage allocation failed. \n"); exit(1); }; ASblock=(iptr *) malloc((orig_constraints+1)*sizeof(iptr)); if (ASblock == NULL) { printf("Storage allocation failed. \n"); exit(1); }; /* * Now allocate vectors for the individual matrices. */ for (i=1; i<=orig_constraints; i++) { ASi[i]=(int *) malloc((entry_counts[i]+1)*sizeof(int)); if (ASi[i] == NULL) { printf("Storage allocation failed. \n"); exit(1); } ASj[i]=(int *) malloc((entry_counts[i]+1)*sizeof(int)); if (ASj[i] == NULL) { printf("Storage allocation failed. \n"); exit(1); } AS[i]=(double *) malloc((entry_counts[i]+1)*sizeof(double)); if (AS[i] == NULL) { printf("Storage allocation failed. \n"); exit(1); } ASblock[i]=(int *) malloc((entry_counts[i]+1)*sizeof(int)); if (ASblock[i] == NULL) { printf("Storage allocation failed. \n"); exit(1); } }; CQ=(double *) malloc((q_vars +1)*sizeof(double)); if (CQ == NULL) { printf("Storage allocation failed. \n"); exit(1); }; AQi=(int *) malloc((aq_entries+1)*sizeof(int)); if (AQi == NULL) { printf("Storage allocation failed. \n"); exit(1); }; AQj=(int *) malloc((aq_entries+1)*sizeof(int)); if (AQj == NULL) { printf("Storage allocation failed. \n"); exit(1); }; AQ=(double *) malloc((aq_entries+1)*sizeof(double)); if (AQ == NULL) { printf("Storage allocation failed. \n"); exit(1); }; CL=(double *) malloc((l_vars+1)*sizeof(double)); if (CL == NULL) { printf("Storage allocation failed. \n"); exit(1); }; ALi=(int *) malloc((al_entries+1)*sizeof(int)); if (ALi == NULL) { printf("Storage allocation failed. \n"); exit(1); }; ALj=(int *) malloc((al_entries+1)*sizeof(int)); if (ALj == NULL) { printf("Storage allocation failed. \n"); exit(1); }; AL=(double *) malloc((al_entries+1)*sizeof(double)); if (AL == NULL) { printf("Storage allocation failed. \n"); exit(1); }; /* * reopen the input file, and read in the problem data. */ fclose(fid); fid=fopen(argv[1],"r"); if (fid == (FILE *) NULL) { printf("Couldn't open SQLP problem file for reading! \n"); exit(1); }; /* * Get the number of constraints. Note that additional constraints are * needed to translate quadratic cone constraints into SDP form. */ ret=fscanf(fid,"%d",&orig_constraints); if (ret != 1) { printf("Incorrect SDPpack file. \n"); exit(1); }; /* * Next, read in the constraint rhs's. */ for (i=1; i<=orig_constraints; i++) { ret=fscanf(fid,"%lf",b+i); if (ret != 1) { printf("Incorrect SDPpack file. \n"); exit(1); }; }; /* * Read in the number of sdp blocks. */ ret=fscanf(fid,"%d",&sdp_blocks); if (ret != 1) { printf("Incorrect SDPpack file. \n"); exit(1); }; if (sdp_blocks != 0) { /* * Next, read in the SDP block sizes. */ for (i=1; i<=sdp_blocks; i++) { ret=fscanf(fid,"%d",&block_size); if (ret != 1) { printf("Incorrect SDPpack file. \n"); exit(1); }; sdp_block_sizes[i]=block_size; }; /* * Next, read in CS */ p=1; base=1; for (k=1; k<=sdp_blocks; k++) { ret=fscanf(fid,"%d",&block_type); if (ret != 1) { printf("Incorrect SDPpack file. \n"); exit(1); }; if (block_type == 0) { /* * Read in a dense block. */ block_size=sdp_block_sizes[k]; for (i=1; i<=block_size; i++) for (j=i; j<=block_size; j++) { fscanf(fid,"%lf",&foo); CSi[p]=i; CSj[p]=j; CS[p]=foo; CSblock[p]=k; p++; }; } else { if (block_type == 1) { /* * Read in a sparse block. */ ret=fscanf(fid,"%d",&num_entries); for (i=1; i<=num_entries; i++) { fscanf(fid,"%d",&indexi); fscanf(fid,"%d",&indexj); fscanf(fid,"%lf",&foo); CSi[p]=indexi; CSj[p]=indexj; CS[p]=foo; CSblock[p]=k; p++; }; } else { printf("Incorrect SDPpack file. \n"); printf("Bad Block Type. \n"); exit(1); }; }; base=base+block_size; }; /* End of loop through blocks of Cs */ /* * Now, read through the A.S constraint matrices. */ for (kk=1; kk<= orig_constraints; kk++) { thisASi=ASi[kk]; thisASj=ASj[kk]; thisAS=AS[kk]; thisASblock=ASblock[kk]; base=1; p=1; for (k=1; k<=sdp_blocks; k++) { ret=fscanf(fid,"%d",&block_type); if (ret != 1) { printf("Incorrect SDPpack file. \n"); exit(1); }; if (block_type == 0) { /* * Read in a dense block. */ block_size=sdp_block_sizes[k]; for (i=1; i<=block_size; i++) for (j=i; j<=block_size; j++) { fscanf(fid,"%lf",&foo); thisASi[p]=i; thisASj[p]=j; thisAS[p]=foo; thisASblock[p]=k; p++; }; } else { if (block_type == 1) { /* * Read in a sparse block. */ ret=fscanf(fid,"%d",&num_entries); for (i=1; i<=num_entries; i++) { fscanf(fid,"%d",&indexi); fscanf(fid,"%d",&indexj); fscanf(fid,"%lf",&foo); thisASi[p]=indexi; thisASj[p]=indexj; thisAS[p]=foo; thisASblock[p]=k; p++; }; } else { printf("Incorrect SDPpack file. \n"); printf("Bad Block Type. \n"); exit(1); }; }; base=base+block_size; }; /* End of loop through blocks of AS */ }; /* End of loop through m constraints. */ } else { /* * Nothing in SDP part of the problem. */ }; /* * Next, read the QC part of the problem. */ ret=fscanf(fid,"%d",&q_blocks); if (ret != 1) { printf("Incorrect SDPpack file. \n"); printf("Bad Block Count. \n"); return(1); }; if (q_blocks != 0) { /* * We've got some QC blocks. */ /* * Read in the block sizes. */ for (i=1; i<=q_blocks; i++) { ret=fscanf(fid,"%d",&block_size); if (ret != 1) { printf("Incorrect SDPpack file. \n"); printf("Bad QC Block Size. \n"); return(1); }; }; /* * Now, read in the cost vector C.q */ for (i=1; i<=q_vars; i++) { ret=fscanf(fid,"%lf",&foo); if (ret != 1) { printf("Incorrect SDPpack file. \n"); printf("Bad C.q entry. \n"); exit(1); }; CQ[i]=foo; }; /* * Next, read in the constraint matrix Aq */ ret=fscanf(fid,"%d",&block_type); if (ret != 1) { printf("Incorrect SDPpack file. \n"); printf("Bad AQ block type. \n"); return(1); }; if (block_type == 0) { /* * Read in a dense AQ matrix. */ p=1; for (j=1; j<=q_vars; j++) for (i=1; i<=orig_constraints; i++) { ret=fscanf(fid,"%lf",&foo); AQi[p]=i; AQj[p]=j; AQ[p]=foo; p++; }; } else { if (block_type == 1) { /* * Read in a sparse AQ matrix. */ p=1; ret=fscanf(fid,"%d",&num_entries); for (i=1; i<=num_entries; i++) { fscanf(fid,"%d",&indexi); fscanf(fid,"%d",&indexj); fscanf(fid,"%lf",&foo); AQi[p]=indexi; AQj[p]=indexj; AQ[p]=foo; p++; }; } else { printf("Incorrect SDPpack file. \n"); printf("Bad AQ type. \n"); return(1); }; }; } else { /* * No QC blocks! */ }; /* * And read the LP part of the problem. */ ret=fscanf(fid,"%d",&l_vars); if (ret != 1) { printf("Incorrect SDPpack file. \n"); printf("Bad linear variable count. (phase 2) \n"); return(1); }; if (l_vars != 0) { /* * Put in one block for the linear variables. */ l_blocks=1; /* * Read in C.l */ for (i=1; i<=l_vars; i++) { ret=fscanf(fid,"%lf",&foo); CL[i]=foo; } /* * Read in the matrix A.l */ ret=fscanf(fid,"%d",&block_type); if (ret != 1) { printf("Incorrect SDPpack file. \n"); printf("Bad AL block type. \n"); return(1); }; if (block_type == 0) { /* * Read in a dense AL matrix. */ p=1; for (j=1; j<=l_vars; j++) for (i=1; i<=orig_constraints; i++) { ret=fscanf(fid,"%lf",&foo); ALi[p]=i; ALj[p]=j; AL[p]=foo; p++; }; } else { if (block_type == 1) { /* * Read in a sparse AL matrix. */ p=1; ret=fscanf(fid,"%d",&num_entries); for (i=1; i<=num_entries; i++) { fscanf(fid,"%d",&indexi); fscanf(fid,"%d",&indexj); fscanf(fid,"%lf",&foo); ALi[p]=indexi; ALj[p]=indexj; AL[p]=foo; p++; }; } else { printf("Incorrect SDPpack file. \n"); printf("Bad AL type. \n"); return(1); }; }; }; /* * Now, go back and write out the problem data in SDPA format. */ /* * Open up the file for output. */ fclose(fid); fid=fopen(argv[2],"w"); if (fid == (FILE *) NULL) { printf("Opening output file failed. \n"); exit(1); }; /* * Write out the basic problem size info. */ fprintf(fid,"%d \n",orig_constraints+extra_constraints); fprintf(fid,"%d \n",sdp_blocks+q_blocks+l_blocks); for (i=1; i<=sdp_blocks; i++) fprintf(fid,"%d ",sdp_block_sizes[i]); for (i=1; i<=q_blocks; i++) fprintf(fid,"%d ",q_block_sizes[i]); if (l_vars != 0) fprintf(fid,"%d ",-l_vars); fprintf(fid,"\n"); /* * Write out the rhs vector. (c in SDPA terminology) */ for (i=1; i<=orig_constraints; i++) fprintf(fid,"%.18e ",b[i]); for (i=1; i<=extra_constraints; i++) fprintf(fid,"%.18e ",0.0); fprintf(fid,"\n"); /* * Write out the C matrix. */ /* * First, CS parts. */ for (j=1; j<=cs_entries; j++) { if (CS[j] != 0.0) fprintf(fid,"0 %d %d %d %.18e \n",CSblock[j],CSi[j],CSj[j],-CS[j]); }; /* * Next, the QC parts. */ for (i=1; i<=q_vars; i++) { if (q_block_offset[i] == 1) { if (CQ[i] != 0.0) fprintf(fid,"0 %d %d %d %.18e \n",which_q_block[i]+sdp_blocks, q_block_offset[i],q_block_offset[i],-CQ[i]); } else { if (CQ[i] != 0.0) fprintf(fid,"0 %d %d %d %.18e \n",which_q_block[i]+sdp_blocks,1, q_block_offset[i],-CQ[i]/2.0); }; }; /* * Next, the LP parts. */ for (i=1; i<=l_vars; i++) { if (CL[i] != 0.0 ) fprintf(fid,"0 %d %d %d %.18e \n",sdp_blocks+q_blocks+1,i,i,-CL[i]); }; /* * Write out the A matrices, one after another. */ /* * First the user's constraints. */ for (i=1; i<=orig_constraints; i++) { /* * First, the SDP part. */ thisASi=ASi[i]; thisASj=ASj[i]; thisAS=AS[i]; thisASblock=ASblock[i]; for (j=1; j<=entry_counts[i]; j++) { if (thisAS[j] != 0.0) fprintf(fid,"%d %d %d %d %.18e \n",i,thisASblock[j],thisASi[j], thisASj[j],thisAS[j]); }; /* * Next, the QC part. */ for (j=1; j<=aq_entries; j++) { if (AQi[j] == i) { if (q_block_offset[AQj[j]] == 1) { if (AQ[j] != 0.0) fprintf(fid,"%d %d %d %d %.18e \n",i,sdp_blocks+which_q_block[AQj[j]],1,1,AQ[j]); } else { if (AQ[j] != 0.0) fprintf(fid,"%d %d %d %d %.18e \n",i,sdp_blocks+which_q_block[AQj[j]], 1,q_block_offset[AQj[j]],AQ[j]/2.0); }; }; }; /* * Finally, the LP part. */ for (j=1; j<=al_entries; j++) { if (ALi[j] == i) { if (AL[j] != 0.0) fprintf(fid,"%d %d %d %d %.18e \n",i,sdp_blocks+q_blocks+1, ALj[j],ALj[j],AL[j]); }; }; }; /* * Next, the extra QC constraints. */ p=1; for (i=1; i<=q_blocks; i++) { for (j=2; j<=q_block_sizes[i]; j++) { fprintf(fid,"%d %d %d %d %.18e \n",p+orig_constraints,i+sdp_blocks, 1,1,1.0); fprintf(fid,"%d %d %d %d %.18e \n",p+orig_constraints,i+sdp_blocks, j,j,-1.0); p=p+1; }; if (q_block_sizes[i] > 2) { for (j=2; j<=q_block_sizes[i]-1; j++) for (k=j+1; k<=q_block_sizes[i]; k++) { fprintf(fid,"%d %d %d %d %.18e \n",p+orig_constraints,i+sdp_blocks, j,k,1.0); p++; }; }; }; /* * Close up and exit. */ fclose(fid); return(0); }