1 #include "dsdpcone_impl.h"
2 #include "dsdpcone.h"
3 #include "dsdpsys.h"
4 
5 /*!
6 \file dsdpcone.c
7 \brief Methods of a cone.
8 */
9 
10 #define DSDPNoOperationError(a);  { DSDPSETERR1(10,"Cone type: %s, Operation not defined\n",(a).dsdpops->name); }
11 #define DSDPChkConeError(a,b);  { if (b){DSDPSETERR1(b,"Cone type: %s,\n",(a).dsdpops->name); } }
12 
13 /*!
14 \fn int DSDPConeSetUp(DSDPCone K, DSDPVec y);
15 
16 \brief Factor the data and allocate data structures.
17 \param K the cone
18 \param y initial solution vector
19 */
20 #undef __FUNCT__
21 #define __FUNCT__ "DSDPConeSetUp"
DSDPConeSetUp(DSDPCone K,DSDPVec y)22 int DSDPConeSetUp(DSDPCone K,DSDPVec y){
23   int info;
24   DSDPFunctionBegin;
25   if (K.dsdpops->conesetup){
26     info=K.dsdpops->conesetup(K.conedata,y);DSDPChkConeError(K,info);
27   } else {
28     DSDPNoOperationError(K);
29   }
30   DSDPFunctionReturn(0);
31 }
32 
33 /*!
34 \fn int DSDPConeSetUp2(DSDPCone K, DSDPVec yy0, DSDPSchurMat M);
35 
36 \brief Factor the data and allocate data structures.
37 \param K the cone
38 \param yy0 initial solution vector
39 \param M Schur matrix
40 */
41 #undef __FUNCT__
42 #define __FUNCT__ "DSDPConeSetUp2"
DSDPConeSetUp2(DSDPCone K,DSDPVec yy0,DSDPSchurMat M)43 int DSDPConeSetUp2(DSDPCone K, DSDPVec yy0, DSDPSchurMat M){
44   int info;
45   DSDPFunctionBegin;
46   if (K.dsdpops->conesetup2){
47     info=K.dsdpops->conesetup2(K.conedata,yy0,M);DSDPChkConeError(K,info);
48   } else {
49     DSDPNoOperationError(K);
50   }
51   DSDPFunctionReturn(0);
52 }
53 
54 
55 /*!
56 \fn int DSDPConeDestroy(DSDPCone *K);
57 
58 \brief Free the internal memory of the cone.
59 \param K the cone
60 
61 */
62 #undef __FUNCT__
63 #define __FUNCT__ "DSDPConeDestroy"
DSDPConeDestroy(DSDPCone * K)64 int DSDPConeDestroy(DSDPCone *K){
65   int info;
66   DSDPFunctionBegin;
67   if ((*K).dsdpops->conedestroy){
68     info=(*K).dsdpops->conedestroy((*K).conedata);DSDPChkConeError(*K,info);
69     info=DSDPConeInitialize(K); DSDPCHKERR(info);
70   } else {
71     DSDPNoOperationError(*K);
72   }
73   DSDPFunctionReturn(0);
74 }
75 
76 
77 /*!
78 \fn int DSDPConeComputeHessian(DSDPCone K, double mu, DSDPSchurMat M,  DSDPVec vrhs1, DSDPVec vrhs2);
79 
80 \brief Compute Hessian and gradient of barrier function.
81 \param K the cone
82 \param mu barrier parameter
83 \param M Schur matrix
84 \param vrhs1 objective gradient
85 \param vrhs2 barrier gradient
86 
87 This routine assumes that the dual matrix has already been factored and inverted.
88 \sa SDPConeComputeHessian()
89 */
90 #undef __FUNCT__
91 #define __FUNCT__ "DSDPConeComputeHessian"
DSDPConeComputeHessian(DSDPCone K,double mu,DSDPSchurMat M,DSDPVec vrhs1,DSDPVec vrhs2)92 int DSDPConeComputeHessian( DSDPCone K , double mu, DSDPSchurMat M,  DSDPVec vrhs1, DSDPVec vrhs2){
93   int info;
94   DSDPFunctionBegin;
95   if (K.dsdpops->conehessian){
96     info=K.dsdpops->conehessian(K.conedata,mu,M,vrhs1,vrhs2);DSDPChkConeError(K,info);
97   } else {
98     DSDPNoOperationError(K);
99   }
100   DSDPFunctionReturn(0);
101 }
102 
103 
104 /*!
105 \fn int DSDPConeMultiplyAdd(DSDPCone K, double mu, DSDPVec vrow, DSDPVec v, DSDPVec vv);
106 
107 \brief Multiply Hessian by a vector and add the result.
108 \param K the cone
109 \param mu barrier parameter
110 \param vrow scaling for each element in the product.
111 \param v input vector gradient
112 \param vv output vector
113 
114 This routine assumes that the dual matrix has already been factored and inverted.
115 If M is the hessian, then vv += vrow .* Mv
116 */
117 #undef __FUNCT__
118 #define __FUNCT__ "DSDPConeMultiplyAdd"
DSDPConeMultiplyAdd(DSDPCone K,double mu,DSDPVec vrow,DSDPVec v,DSDPVec vv)119 int DSDPConeMultiplyAdd( DSDPCone K , double mu, DSDPVec vrow, DSDPVec v, DSDPVec vv){
120   int info;
121   DSDPFunctionBegin;
122   if (K.dsdpops->conehmultiplyadd){
123     info=K.dsdpops->conehmultiplyadd(K.conedata,mu,vrow,v,vv);DSDPChkConeError(K,info);
124   } else {
125     DSDPNoOperationError(K);
126   }
127   DSDPFunctionReturn(0);
128 }
129 
130 
131 /*!
132 \fn int DSDPConeComputeRHS(DSDPCone K, double mu, DSDPVec vrow, DSDPVec rhs1, DSDPVec rhs2);
133 
134 \brief Compute gradient of barrier function.
135 \param K the cone
136 \param mu barrier parameter
137 \param vrow scaling for each element in the gradient.
138 \param rhs1 objective gradient
139 \param rhs2 barrier gradient
140 
141 This routine assumes that the dual matrix has already been factored and inverted.
142 Define rhs2 += mu * vrow .* A(S^{-1})
143 \sa SDPConeComputeRHS()
144 */
145 #undef __FUNCT__
146 #define __FUNCT__ "DSDPConeComputeRHS"
DSDPConeComputeRHS(DSDPCone K,double mu,DSDPVec vrow,DSDPVec rhs1,DSDPVec rhs2)147 int DSDPConeComputeRHS( DSDPCone K , double mu, DSDPVec vrow,DSDPVec rhs1,DSDPVec rhs2){
148   int info;
149   DSDPFunctionBegin;
150   if (K.dsdpops->conerhs){
151     info=K.dsdpops->conerhs(K.conedata,mu,vrow,rhs1,rhs2);DSDPChkConeError(K,info);
152   } else {
153     DSDPNoOperationError(K);
154   }
155   DSDPFunctionReturn(0);
156 }
157 
158 /*!
159 \fn int DSDPConeANorm2(DSDPCone K, DSDPVec anorm2);
160 
161 \brief Add square of 2-norm of data correponding to each variable y.
162 \param K the cone
163 \param anorm2 norm of constraint data for each varibles
164 \sa DSDPBlockANorm2
165 */
166 #undef __FUNCT__
167 #define __FUNCT__ "DSDPConeANorm2"
DSDPConeANorm2(DSDPCone K,DSDPVec anorm2)168 int DSDPConeANorm2( DSDPCone K , DSDPVec anorm2){
169   int info;
170   DSDPFunctionBegin;
171   if (K.dsdpops->coneanorm2){
172     info=K.dsdpops->coneanorm2(K.conedata,anorm2);DSDPChkConeError(K,info);
173   } else {
174     DSDPNoOperationError(K);
175   }
176   DSDPFunctionReturn(0);
177 }
178 
179 /*!
180 \fn int DSDPConeSetXMaker(DSDPCone K, double mu, DSDPVec y, DSDPVec dy);
181 
182 \brief Pass information needed to construct X.
183 \param K the cone
184 \param mu barrier parameter
185 \param y solution
186 \param dy step direction
187 
188 */
189 #undef __FUNCT__
190 #define __FUNCT__ "DSDPConeSetXMaker"
DSDPConeSetXMaker(DSDPCone K,double mu,DSDPVec y,DSDPVec dy)191 int DSDPConeSetXMaker( DSDPCone K, double mu, DSDPVec y, DSDPVec dy){
192   int info;
193   DSDPFunctionBegin;
194   if (K.dsdpops->conesetxmaker){
195     info=K.dsdpops->conesetxmaker(K.conedata,mu,y,dy);DSDPChkConeError(K,info);
196   } else {
197     DSDPNoOperationError(K);
198   }
199   DSDPFunctionReturn(0);
200 }
201 
202 /*!
203 \fn int DSDPConeComputeX(DSDPCone K, double mu, DSDPVec y, DSDPVec dy, DSDPVec AX, double *tracexs);
204 
205 \brief Given y,dy, and mu, construct X and add its inner product with the data and S
206 \param K the cone
207 \param mu barrier parameter
208 \param y solution
209 \param dy step direction
210 \param AX add the inner product of the data with X
211 \param tracexs inner product of X and S.
212 \sa SDPConeComputeXX()
213 */
214 #undef __FUNCT__
215 #define __FUNCT__ "DSDPConeComputeX"
DSDPConeComputeX(DSDPCone K,double mu,DSDPVec y,DSDPVec dy,DSDPVec AX,double * tracexs)216 int DSDPConeComputeX( DSDPCone K, double mu, DSDPVec y, DSDPVec dy, DSDPVec AX, double *tracexs){
217   int info;
218   double trxs;
219   DSDPFunctionBegin;
220   if (K.dsdpops->conecomputex){
221     trxs=0;
222     info=K.dsdpops->conecomputex(K.conedata,mu,y,dy,AX,&trxs);DSDPChkConeError(K,info);
223     *tracexs+=trxs;
224   } else {
225     DSDPNoOperationError(K);
226   }
227   DSDPFunctionReturn(0);
228 }
229 
230 /*!
231 \fn int DSDPConeComputeS(DSDPCone K, DSDPVec Y, DSDPDualFactorMatrix flag, DSDPTruth *ispsdefinite);
232 
233 \brief Given y, compute S and determine whether its in the cone.
234 \param K the cone
235 \param Y solution
236 \param flag identifies which of two S matrix structures should be used.
237 \param ispsdefinite true if S is positive definite or an element of the cone.
238 
239 */
240 #undef __FUNCT__
241 #define __FUNCT__ "DSDPConeComputeS"
DSDPConeComputeS(DSDPCone K,DSDPVec Y,DSDPDualFactorMatrix flag,DSDPTruth * ispsdefinite)242 int DSDPConeComputeS(DSDPCone K, DSDPVec Y, DSDPDualFactorMatrix flag, DSDPTruth *ispsdefinite){
243   int info;
244   DSDPFunctionBegin;
245   if (K.dsdpops->conecomputes){
246     info=K.dsdpops->conecomputes(K.conedata,Y,flag,ispsdefinite);DSDPChkConeError(K,info);
247   } else {
248     DSDPNoOperationError(K);
249   }
250   DSDPFunctionReturn(0);
251 }
252 
253 
254 /*!
255 \fn int DSDPConeInvertS(DSDPCone K);
256 
257 \brief Invert the dual matrix S.
258 \param K the cone
259 
260 Assumes that the matrix has already been factored.
261 
262 */
263 #undef __FUNCT__
264 #define __FUNCT__ "DSDPConeInvertS"
DSDPConeInvertS(DSDPCone K)265 int DSDPConeInvertS(DSDPCone K){
266   int info;
267   DSDPFunctionBegin;
268   if (K.dsdpops->coneinverts){
269     info=K.dsdpops->coneinverts(K.conedata);DSDPChkConeError(K,info);
270   } else {
271     DSDPNoOperationError(K);
272   }
273   DSDPFunctionReturn(0);
274 }
275 
276 /*!
277 \fn int DSDPConeComputeMaxStepLength(DSDPCone K, DSDPVec DY, DSDPDualFactorMatrix flag, double *maxsteplength);
278 
279 \brief Determine distance to the edge of the cone.
280 \param K the cone
281 \param DY step direction
282 \param flag identifies which of two S matrix structures should be used.
283 \param maxsteplength distance to the edge of the cone.
284 
285 */
286 #undef __FUNCT__
287 #define __FUNCT__ "DSDPConeComputeMaxStepLength"
DSDPConeComputeMaxStepLength(DSDPCone K,DSDPVec DY,DSDPDualFactorMatrix flag,double * maxsteplength)288 int DSDPConeComputeMaxStepLength(DSDPCone K, DSDPVec DY, DSDPDualFactorMatrix flag, double *maxsteplength){
289   int info;
290   double conesteplength=1.0e20;
291   DSDPFunctionBegin;
292   conesteplength=1.0e30;
293   if (K.dsdpops->conemaxsteplength){
294     info=K.dsdpops->conemaxsteplength(K.conedata,DY,flag,&conesteplength);DSDPChkConeError(K,info);
295   } else {
296     DSDPNoOperationError(K);
297   }
298   *maxsteplength=conesteplength;
299   DSDPFunctionReturn(0);
300 }
301 
302 /*!
303 \fn int DSDPConeGetDimension(DSDPCone K, double *n);
304 
305 \brief Provide the dimension of the cone.
306 \param K the cone
307 \param n conic dimension (an integer value)
308 
309 */
310 #undef __FUNCT__
311 #define __FUNCT__ "DSDPConeGetDimension"
DSDPConeGetDimension(DSDPCone K,double * n)312 int DSDPConeGetDimension(DSDPCone K, double *n){
313   int info;
314   double nn=0;
315   DSDPFunctionBegin;
316   if (K.dsdpops->conesize){
317     info=K.dsdpops->conesize(K.conedata,&nn);DSDPChkConeError(K,info);
318   } else {
319     DSDPNoOperationError(K);
320   }
321   *n=nn;
322   DSDPFunctionReturn(0);
323 }
324 
325 /*!
326 \fn int DSDPConeSparsityInSchurMat(DSDPCone K, int row, int rnnz[], int m);
327 
328 \brief Identify sparsity pattern in a row of the Hessian term
329 \param K the cone
330 \param row between 1 and m
331 \param rnnz mark elements nonzero for nonzeros in Hessian of barrier.
332 \param m number of y variables, length of array, and size of M matrix
333 \sa DSDPSparsityInSchurMat()
334 \sa DSDPSchurSparsity()
335 */
336 #undef __FUNCT__
337 #define __FUNCT__ "DSDPSparsityInSchurMat"
DSDPConeSparsityInSchurMat(DSDPCone K,int row,int rnnz[],int m)338 int DSDPConeSparsityInSchurMat(DSDPCone K, int row, int rnnz[], int m){
339   int info,tt;
340   DSDPFunctionBegin;
341   if (K.dsdpops->conesparsity){
342     info=K.dsdpops->conesparsity(K.conedata,row,&tt,rnnz,m);DSDPChkConeError(K,info);
343   } else {
344     DSDPNoOperationError(K);
345   }
346   DSDPFunctionReturn(0);
347 }
348 
349 /*!
350 \fn int DSDPConeView(DSDPCone K);
351 
352 \brief View contents of the cone.
353 \param K the cone
354 
355 */
356 #undef __FUNCT__
357 #define __FUNCT__ "DSDPConeView"
DSDPConeView(DSDPCone K)358 int DSDPConeView(DSDPCone K){
359   int info;
360   DSDPFunctionBegin;
361   if (K.dsdpops->coneview){
362     info=K.dsdpops->coneview(K.conedata);DSDPChkConeError(K,info);
363   } else {
364     DSDPNoOperationError(K);
365   }
366   DSDPFunctionReturn(0);
367 }
368 
369 /*!
370 \fn int DSDPConeMonitor(DSDPCone K, int tag);
371 
372 \brief Do anything at in the cone at each iteration.
373 \param K the cone
374 \param tag allows for multiple types of monitors.
375 
376 This routine has be used to visualize data, print some statistics, ...
377 */
378 #undef __FUNCT__
379 #define __FUNCT__ "DSDPConeMonitor"
DSDPConeMonitor(DSDPCone K,int tag)380 int DSDPConeMonitor(DSDPCone K, int tag){
381   int info;
382   DSDPFunctionBegin;
383   if (K.dsdpops->conemonitor){
384     info=K.dsdpops->conemonitor(K.conedata,tag);DSDPChkConeError(K,info);
385   } else {
386     DSDPNoOperationError(K);
387   }
388   DSDPFunctionReturn(0);
389 }
390 
391 
392 /*!
393 \fn int DSDPConeComputeLogSDeterminant(DSDPCone K, double *logdetobj, double *logdet);
394 
395 \brief Evaluate logrithmic barrier function.
396 \param K the cone
397 \param logdetobj used term.
398 \param logdet logarithmic barrier of cone
399 Assumes S is in cone.
400 */
401 #undef __FUNCT__
402 #define __FUNCT__ "DSDPConeComputeLogSDeterminant"
DSDPConeComputeLogSDeterminant(DSDPCone K,double * logdetobj,double * logdet)403 int DSDPConeComputeLogSDeterminant(DSDPCone K, double *logdetobj, double *logdet){
404   int info;
405   double conepotential1=0,conepotential2=0;
406   DSDPFunctionBegin;
407   if (K.dsdpops->conelogpotential){
408       info=K.dsdpops->conelogpotential(K.conedata,&conepotential1,&conepotential2);DSDPChkConeError(K,info);
409   } else {
410     DSDPNoOperationError(K);
411   }
412   *logdetobj=conepotential1;
413   *logdet=conepotential2;
414   DSDPFunctionReturn(0);
415 }
416 
417 /*!
418 \fn int DSDPGetConeName(DSDPCone K, char *cname, int maxlength);
419 
420 \brief Get name of the cone.
421 \param K the cone
422 \param cname string to copy the string
423 \param maxlength maximum length of the string.
424 */
425 #undef __FUNCT__
426 #define __FUNCT__ "DSDPGetConeName"
DSDPGetConeName(DSDPCone K,char * cname,int maxlength)427 int DSDPGetConeName(DSDPCone K, char *cname, int maxlength){
428   DSDPFunctionBegin;
429   strncpy(cname,K.dsdpops->name,maxlength);
430   DSDPFunctionReturn(0);
431 }
432 
433 
434 
435 /*!
436 \fn int DSDPConeOpsInitialize(struct DSDPCone_Ops* dops);
437 
438 \brief Initialize the function pointers to 0.
439 \param dops address of a structure of function pointers.
440 */
441 #undef __FUNCT__
442 #define __FUNCT__ "DSDPConeOpsInitialize"
DSDPConeOpsInitialize(struct DSDPCone_Ops * dops)443 int DSDPConeOpsInitialize(struct  DSDPCone_Ops* dops){
444   DSDPFunctionBegin;
445   if (dops==NULL) return 0;
446 
447   dops->conesetup=0;
448   dops->conesetup2=0;
449   dops->conedestroy=0;
450   dops->coneanorm2=0;
451   dops->conehessian=0;
452   dops->conehmultiplyadd=0;
453   dops->conerhs=0;
454   dops->conesetxmaker=0;
455   dops->conecomputex=0;
456   dops->conecomputes=0;
457   dops->coneinverts=0;
458   dops->conemaxsteplength=0;
459   dops->conesparsity=0;
460   dops->conelogpotential=0;
461   dops->conemonitor=0;
462   dops->coneview=0;
463   dops->id=0;
464   DSDPFunctionReturn(0);
465 }
466 
467 /*!
468 \fn int DSDPConeSetData(DSDPCone *K, struct DSDPCone_Ops* ops,  void* data);
469 
470 \brief Initialize the pointers to 0.
471 \param K the cone
472 \param ops address of a structure of function pointers.
473 \param data address of a structure representing a cone
474 */
475 #undef __FUNCT__
476 #define __FUNCT__ "DSDPConeSetData"
DSDPConeSetData(DSDPCone * K,struct DSDPCone_Ops * ops,void * data)477 int DSDPConeSetData(DSDPCone *K, struct DSDPCone_Ops* ops,  void* data){
478   DSDPFunctionBegin;
479   (*K).dsdpops=ops;
480   (*K).conedata=data;
481   DSDPFunctionReturn(0);
482 }
483 
484 
485 static struct  DSDPCone_Ops dsdpcops;
486 /*!
487 \fn int DSDPConeInitialize(DSDPCone *K);
488 
489 \brief Initialize the pointers to 0.
490 \param K the cone
491 
492 */
493 #undef __FUNCT__
494 #define __FUNCT__ "DSDPConeOpsInitialize"
DSDPConeInitialize(DSDPCone * K)495 int DSDPConeInitialize(DSDPCone *K){
496   int info;
497   DSDPFunctionBegin;
498   info=DSDPConeOpsInitialize(&dsdpcops); DSDPCHKERR(info);
499   info=DSDPConeSetData(K,&dsdpcops,0); DSDPCHKERR(info);
500   DSDPFunctionReturn(0);
501 }
502 
503