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