sdpa-python 0.2.1__cp312-cp312-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sdpap/fileio.py ADDED
@@ -0,0 +1,803 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ Routines to read/write files from/to CLP and SDPA sparse format
4
+ This file is a component of SDPAP
5
+ Copyright (C) 2010-2022 SDPA Project
6
+
7
+ This program is free software; you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation; either version 2 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License along
18
+ with this program; if not, write to the Free Software Foundation, Inc.,
19
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
+
21
+ September 2010: Originally written by Kenta Kato
22
+ December 2010: Modified for SciPy
23
+ """
24
+
25
+ __all__ = ['readproblem', 'writeproblem', 'fromsdpa', 'tosdpa']
26
+
27
+ from . import convert
28
+ from .symcone import SymCone
29
+ from scipy.sparse import csc_matrix, csr_matrix
30
+ from scipy import sparse
31
+
32
+
33
+ def readproblem(filename):
34
+ """Read problem file and make CLP
35
+
36
+ Args:
37
+ filename: A string of file pass for CLP format problem
38
+ Input file format:
39
+ J.f
40
+ J.l
41
+ J.q -> Each numbers are split by " "(white space).
42
+ If J.q = (), write 0.
43
+ J.s -> Each numbers are split by " ". if J.s = (), write 0.
44
+ K.f
45
+ K.l
46
+ K.q -> Each numbers are split by " ". if K.q = (), write 0.
47
+ K.s -> Each numbers are split by " ". if K.s = (), write 0.
48
+ ROW COL row col val -> Each numbers are split by " ".
49
+ ROW COL row col val
50
+ : : : : :
51
+ : : : : :
52
+
53
+ (ROW,COL,row,col,val) means:
54
+ The value of (row,col) element in (ROW,COL) block of A is val
55
+ (ROW,COL,row,col are indexed 1,2,3,...)
56
+ If ROW = 0: the value of col's element in
57
+ COL's block of c is val (row = 0(recommended))
58
+ If COL = 0: the value of row's element in
59
+ ROW's block of b is val (col = 0(recommended))
60
+
61
+ Returns:
62
+ A tuple of CLP problem input (A, b, c, K, J)
63
+ """
64
+ if not isinstance(filename, str):
65
+ print("readproblem(): filename must be string.")
66
+ return
67
+
68
+ fp = open(filename, "r")
69
+ # Read J
70
+ J_f = int(fp.readline())
71
+ J_l = int(fp.readline())
72
+ line = [int(x) for x in fp.readline().rstrip().split(" ")]
73
+ J_q = tuple(line) if line[0] != 0 else ()
74
+ line = [int(x) for x in fp.readline().rstrip().split(" ")]
75
+ J_s = tuple(line) if line[0] != 0 else ()
76
+ J = SymCone(J_f, J_l, J_q, J_s)
77
+
78
+ # Read K
79
+ K_f = int(fp.readline())
80
+ K_l = int(fp.readline())
81
+ line = [int(x) for x in fp.readline().rstrip().split(" ")]
82
+ K_q = tuple(line) if line[0] != 0 else ()
83
+ line = [int(x) for x in fp.readline().rstrip().split(" ")]
84
+ K_s = tuple(line) if line[0] != 0 else ()
85
+ K = SymCone(K_f, K_l, K_q, K_s)
86
+
87
+ start_row = [0]
88
+ if J.f != 0:
89
+ start_row.append(J.f)
90
+
91
+ if J.l != 0:
92
+ start_row.append(start_row[-1] + J.l)
93
+
94
+ for k in J.q:
95
+ start_row.append(start_row[-1] + k)
96
+
97
+ for k in J.s:
98
+ start_row.append(start_row[-1] + k ** 2)
99
+
100
+ start_col = [0]
101
+ if K.f != 0:
102
+ start_col.append(K.f)
103
+
104
+ if K.l != 0:
105
+ start_col.append(start_col[-1] + K.l)
106
+
107
+ for k in K.q:
108
+ start_col.append(start_col[-1] + k)
109
+
110
+ for k in K.s:
111
+ start_col.append(start_col[-1] + k ** 2)
112
+
113
+ size_row = J.f + J.l + sum(J.q) + sum([k ** 2 for k in J.s])
114
+ size_col = K.f + K.l + sum(K.q) + sum([k ** 2 for k in K.s])
115
+
116
+ # Read I,J,i,j,v
117
+ A_row = []
118
+ A_col = []
119
+ A_val = []
120
+ b_index = []
121
+ b_val = []
122
+ c_index = []
123
+ c_val = []
124
+
125
+ for line in fp.readlines():
126
+ ROW, COL, row, col, val = line.rstrip().split(" ")[0:5]
127
+ if float(val)==0:
128
+ continue
129
+ if int(ROW) == 0:
130
+ c_index.append(start_col[int(COL) - 1] + int(col) - 1)
131
+ c_val.append(float(val))
132
+ elif int(COL) == 0:
133
+ b_index.append(start_row[int(ROW) - 1] + int(row) - 1)
134
+ b_val.append(float(val))
135
+ else:
136
+ A_row.append(start_row[int(ROW) - 1] + int(row) - 1)
137
+ A_col.append(start_col[int(COL) - 1] + int(col) - 1)
138
+ A_val.append(float(val))
139
+
140
+ A = csc_matrix((A_val, (A_row, A_col)), shape=(size_row, size_col))
141
+ b = csc_matrix((b_val, (b_index, [0] * len(b_index))), shape=(size_row, 1))
142
+ c = csc_matrix((c_val, (c_index, [0] * len(c_index))), shape=(size_col, 1))
143
+
144
+ fp.close()
145
+
146
+ return A, b, c, K, J
147
+
148
+
149
+ def writeproblem(filename, A, b, c, K, J, accuracy="%+8.16e"):
150
+ """Write CLP to file
151
+
152
+ Args:
153
+ filename: A string of file pass
154
+ A, b, c: Scipy matrices to denote the CLP
155
+ K, J: Symcone object to denote the CLP
156
+ accuracy: Print format
157
+ """
158
+ if not isinstance(filename, str):
159
+ raise ValueError("writeproblem(): filename must be string.")
160
+
161
+ if not sparse.isspmatrix_csc(b):
162
+ b = csc_matrix(b)
163
+
164
+ if not sparse.isspmatrix_csc(c):
165
+ c = csc_matrix(c)
166
+
167
+ if not sparse.isspmatrix_csr(A):
168
+ A = csr_matrix(A)
169
+
170
+ fp = open(filename, "w")
171
+ # Write J
172
+ fp.write(str(J.f) + "\n")
173
+ fp.write(str(J.l) + "\n")
174
+ if len(J.q) > 0:
175
+ fp.write(" ".join([str(num) for num in J.q]) + "\n")
176
+ else:
177
+ fp.write("0\n")
178
+ if len(J.s) > 0:
179
+ fp.write(" ".join([str(num) for num in J.s]) + "\n")
180
+ else:
181
+ fp.write("0\n")
182
+
183
+ # Write K
184
+ fp.write(str(K.f) + "\n")
185
+ fp.write(str(K.l) + "\n")
186
+ if len(K.q) > 0:
187
+ fp.write(" ".join([str(num) for num in K.q]) + "\n")
188
+ else:
189
+ fp.write("0\n")
190
+ if len(K.s) > 0:
191
+ fp.write(" ".join([str(num) for num in K.s]) + "\n")
192
+ else:
193
+ fp.write("0\n")
194
+
195
+ start_row = [0]
196
+ if J.f != 0:
197
+ start_row.append(J.f)
198
+
199
+ if J.l != 0:
200
+ start_row.append(start_row[-1] + J.l)
201
+
202
+ for k in J.q:
203
+ start_row.append(start_row[-1] + k)
204
+
205
+ for k in J.s:
206
+ start_row.append(start_row[-1] + k ** 2)
207
+
208
+ start_col = [0]
209
+ if K.f != 0:
210
+ start_col.append(K.f)
211
+
212
+ if K.l != 0:
213
+ start_col.append(start_col[-1] + K.l)
214
+
215
+ for k in K.q:
216
+ start_col.append(start_col[-1] + k)
217
+
218
+ for k in K.s:
219
+ start_col.append(start_col[-1] + k ** 2)
220
+
221
+ size_row = J.f + J.l + sum(J.q) + sum([k ** 2 for k in J.s])
222
+ size_col = K.f + K.l + sum(K.q) + sum([k ** 2 for k in K.s])
223
+
224
+ # Split matrix
225
+ c_block = [c[start_col[i]:start_col[i+1]]
226
+ for i in range(len(start_col) - 1)]
227
+ b_block = [b[start_row[i]:start_row[i+1]]
228
+ for i in range(len(start_row) - 1)]
229
+ tmp_block = [A[start_row[i]:start_row[i+1], :]
230
+ for i in range(len(start_row) - 1)]
231
+
232
+ A_block = []
233
+ for T in tmp_block:
234
+ A_block.append([T[:, start_col[i]:start_col[i+1]]
235
+ for i in range(len(start_col) - 1)])
236
+
237
+ # Write c
238
+ for COL in range(len(start_col) - 1):
239
+ block = c_block[COL]
240
+ list_row = ["0"] * len(list(block.nonzero()[0]))
241
+ list_col = [str(x + 1) for x in list(block.nonzero()[0])]
242
+ list_val = [accuracy % x for x in list(block.data)]
243
+ for (row, col, val) in zip(list_row, list_col, list_val):
244
+ fp.write(" ".join(["0", str(COL + 1), row, col, val]) + "\n")
245
+
246
+ # Write b
247
+ for ROW in range(len(start_row) - 1):
248
+ block = b_block[ROW]
249
+ list_row = [str(x + 1) for x in list(block.nonzero()[0])]
250
+ list_col = ["0"] * len(list(block.nonzero()[0]))
251
+ list_val = [accuracy % x for x in list(block.data)]
252
+ for (row, col, val) in zip(list_row, list_col, list_val):
253
+ fp.write(" ".join([str(ROW + 1), "0", row, col, val]) + "\n")
254
+
255
+ # Write A
256
+ for ROW in range(len(start_row) - 1):
257
+ for COL in range(len(start_col) - 1):
258
+ block = A_block[ROW][COL]
259
+ list_row = [str(x + 1) for x in list(block.nonzero()[0])]
260
+ list_col = [str(x + 1) for x in list(block.nonzero()[1])]
261
+ list_val = [accuracy % x for x in list(block.data)]
262
+ for (row, col, val) in zip(list_row, list_col, list_val):
263
+ fp.write(" ".join([str(ROW + 1), str(COL + 1),
264
+ row, col, val]) + "\n")
265
+
266
+ fp.close()
267
+ return
268
+
269
+
270
+ def fromsdpa(filename):
271
+ """Convert from SDPA sparse format to CLP format
272
+
273
+ Args:
274
+ filename: A string of file pass for SDPA sparse format
275
+
276
+ Returns:
277
+ A tuple of CLP problem input, (A, b, c, K, J)
278
+ """
279
+ if not isinstance(filename, str):
280
+ print('fromsdpa(): filename must be string')
281
+ return
282
+
283
+ K = SymCone()
284
+ J = SymCone()
285
+
286
+ # skip comment
287
+ fp = open(filename, 'r')
288
+ line = fp.readline()
289
+ while line[0] == '*' or line[0] == '"':
290
+ line = fp.readline()
291
+
292
+ # read mDim
293
+ J.f = int(line.strip().split(' ')[0])
294
+
295
+ # read nBlock
296
+ line = fp.readline()
297
+ nBlock = int(line.strip().split(' ')[0])
298
+
299
+ # read blockStruct
300
+ blockStruct = []
301
+ structSOCP = []
302
+ structSDP = []
303
+ line = fp.readline()
304
+ blockStruct = line.strip().split(' ')
305
+ while blockStruct.count('') > 0:
306
+ blockStruct.remove('')
307
+
308
+ blockSize = []
309
+ blockType = []
310
+ for i in range(nBlock):
311
+ item = blockStruct[i]
312
+ size = abs(int(item[0:-1])) if item[-1] in 'FLQS' else abs(int(item))
313
+ blockSize.append(size)
314
+
315
+ if item[-1] == 'F':
316
+ K.f += size
317
+ blockType.append('F')
318
+ elif item[-1] == 'L':
319
+ K.l += size
320
+ blockType.append('L')
321
+ elif item[-1] == 'Q':
322
+ structSOCP.append(size)
323
+ blockType.append('Q')
324
+ elif item[-1] == 'S':
325
+ structSDP.append(size)
326
+ blockType.append('S')
327
+ else:
328
+ st = int(item)
329
+ if st > 0:
330
+ structSDP.append(st)
331
+ blockType.append('S')
332
+ else:
333
+ K.l -= st
334
+ blockType.append('L')
335
+
336
+ K.q = tuple(structSOCP)
337
+ K.s = tuple(structSDP)
338
+
339
+ # read b
340
+ line = fp.readline()
341
+ line = line.strip()
342
+ line = line.strip('{}()')
343
+ if ',' in line:
344
+ b_str = line.strip().split(',')
345
+ else:
346
+ b_str = line.strip().split()
347
+ while b_str.count('') > 0:
348
+ b_str.remove('')
349
+
350
+ """
351
+ The documented way to use `csr_matrix` is to provide it an ndarray
352
+ of rank-2. However, directly providing a list seems to work as well.
353
+ If in future this causes a problem, wrap the argument of `csr_matrix`
354
+ with np.array([...])
355
+ """
356
+ b = csr_matrix(list(map(float, [s for s in b_str]))).T
357
+
358
+ # read c and A
359
+ blockElements_c = [[] for i in range(nBlock)]
360
+ blockElements_A = [[] for i in range(nBlock)]
361
+ lineList = fp.readlines()
362
+ for line in lineList:
363
+ row, block, colI, colJ, val = line.split()[0:5]
364
+ row = int(row.strip(',')) - 1
365
+ # if (row+1) > J.f:
366
+ # break
367
+ block = int(block.strip(',')) - 1
368
+ colI = int(colI.strip(',')) - 1
369
+ colJ = int(colJ.strip(',')) - 1
370
+ val = float(val.strip(','))
371
+ if val==0:
372
+ continue
373
+ col = colI * blockSize[block] + colJ \
374
+ if blockType[block] == 'S' else colI
375
+ col2 = colJ * blockSize[block] + colI \
376
+ if blockType[block] == 'S' else colJ
377
+
378
+ if row == -1:
379
+ blockElements_c[block].append((col, val))
380
+ if blockType[block] == 'S' and colI != colJ:
381
+ blockElements_c[block].append((col2, val))
382
+ else:
383
+ blockElements_A[block].append((row, col, val))
384
+ if blockType[block] == 'S' and colI != colJ:
385
+ blockElements_A[block].append((row, col2, val))
386
+
387
+ for block in range(nBlock):
388
+ blockElements_c[block].sort()
389
+ blockElements_A[block].sort(key = lambda x: x[1])
390
+
391
+ elementsK_c = {'F':[[], []], 'L':[[], []], 'Q':[[], []], 'S':[[], []]}
392
+ elementsK_A = {'F':[[], [], []], 'L':[[], [], []],
393
+ 'Q':[[], [], []], 'S':[[], [], []]}
394
+ offsetK = {'F':0, 'L':0, 'Q':0, 'S':0}
395
+
396
+ for block in range(nBlock):
397
+ for item in blockElements_c[block]:
398
+ elementsK_c[blockType[block]][0].append(item[0] +
399
+ offsetK[blockType[block]])
400
+ elementsK_c[blockType[block]][1].append(item[1])
401
+
402
+ for item in blockElements_A[block]:
403
+ elementsK_A[blockType[block]][0].append(item[0])
404
+ elementsK_A[blockType[block]][1].append(item[1] +
405
+ offsetK[blockType[block]])
406
+ elementsK_A[blockType[block]][2].append(item[2])
407
+
408
+ offsetK[blockType[block]] += blockSize[block] ** 2 \
409
+ if blockType[block] == 'S' \
410
+ else blockSize[block]
411
+
412
+ elements_c = [[], []]
413
+ elements_A = [[], [], []]
414
+ offset = 0
415
+
416
+ if K.f > 0:
417
+ elements_c[0].extend(elementsK_c['F'][0])
418
+ elements_c[1].extend(elementsK_c['F'][1])
419
+ elements_A[0].extend(elementsK_A['F'][0])
420
+ elements_A[1].extend(elementsK_A['F'][1])
421
+ elements_A[2].extend(elementsK_A['F'][2])
422
+ offset += K.f
423
+
424
+ if K.l > 0:
425
+ elements_c[0].extend([x + offset for x in elementsK_c['L'][0]])
426
+ elements_c[1].extend(elementsK_c['L'][1])
427
+ elements_A[0].extend(elementsK_A['L'][0])
428
+ elements_A[1].extend([x + offset for x in elementsK_A['L'][1]])
429
+ elements_A[2].extend(elementsK_A['L'][2])
430
+ offset += K.l
431
+
432
+ if True: #K.q > 0:
433
+ elements_c[0].extend([x + offset for x in elementsK_c['Q'][0]])
434
+ elements_c[1].extend(elementsK_c['Q'][1])
435
+ elements_A[0].extend(elementsK_A['Q'][0])
436
+ elements_A[1].extend([x + offset for x in elementsK_A['Q'][1]])
437
+ elements_A[2].extend(elementsK_A['Q'][2])
438
+ offset += sum(K.q)
439
+
440
+ if True: #K.s > 0:
441
+ elements_c[0].extend([x + offset for x in elementsK_c['S'][0]])
442
+ elements_c[1].extend(elementsK_c['S'][1])
443
+ elements_A[0].extend(elementsK_A['S'][0])
444
+ elements_A[1].extend([x + offset for x in elementsK_A['S'][1]])
445
+ elements_A[2].extend(elementsK_A['S'][2])
446
+ offset += sum([x ** 2 for x in K.s])
447
+
448
+ size_K = offset
449
+
450
+ c = csc_matrix((elements_c[1], (elements_c[0], [0] * len(elements_c[0]))),
451
+ shape=(size_K, 1))
452
+ A = csc_matrix((elements_A[2], (elements_A[0], elements_A[1])),
453
+ shape=(J.f, size_K))
454
+
455
+ return A, b, c, K, J
456
+
457
+
458
+ def tosdpa(filename, A, b, c, K, J, accuracy="%+8.16e"):
459
+ """Convert from SeDuMi format to SDPA sparse format
460
+
461
+ If J.l or J.q or J.s are not empty, CLP format will be converted
462
+ to SeDuMi format first.
463
+
464
+ Args:
465
+ filename: A string of file pass
466
+ A, b, c: Scipy matrices to denote the CLP
467
+ K, J: Symcone object to denote the CLP
468
+ accuracy: Print format (e.g. '%8.16e')
469
+ """
470
+ if accuracy[0] != "%":
471
+ raise ValueError("accuracy must start with %% (e.g. %8.16e) \n")
472
+
473
+ if not isinstance(K, SymCone) or not isinstance(J, SymCone):
474
+ raise ValueError('K and J must be an instance of SymCone.')
475
+
476
+ if not K.check_validity() or not J.check_validity():
477
+ return
478
+
479
+ if J.l > 0 or len(J.q) > 0 or len(J.s) > 0:
480
+ raise ValueError("SymCone J must only have attribute 'f'")
481
+
482
+ if not sparse.isspmatrix_csr(A):
483
+ A = csr_matrix(A)
484
+ if not sparse.isspmatrix_csc(b):
485
+ b = csc_matrix(b)
486
+ if not sparse.isspmatrix_csc(c):
487
+ c = csc_matrix(c)
488
+
489
+ # Note that primal-dual is reverse in SeDuMi.
490
+ # So c2 must be -c2.
491
+ # In addition, A2 should be passed in the transposed style.
492
+ # December 2023 edit: to maintain consistency with `writeproblem` method
493
+ # (that exports to CLP format) this sign flipping is being omitted here.
494
+ c2 = c
495
+ b2 = b
496
+ A2 = A
497
+
498
+ fp = open(filename, "w")
499
+
500
+ size_row, size_col = A2.shape
501
+ # write mDim
502
+ fp.write(str(size_row) + "\n")
503
+
504
+ # write nBlock
505
+ fp.write(str(int(K.f > 0) + int(K.l > 0) + len(K.q) + len(K.s)) + "\n")
506
+
507
+ print(J)
508
+ print(K)
509
+
510
+ # write blockStruct
511
+ blockStruct = []
512
+ if K.f > 0:
513
+ blockStruct.append(str(K.f) + "F")
514
+
515
+ if K.l > 0:
516
+ blockStruct.append(str(K.l) + "L")
517
+
518
+ if len(K.q) > 0:
519
+ blockStruct.extend([str(x) + "Q" for x in K.q])
520
+
521
+ if len(K.s) > 0:
522
+ blockStruct.extend([str(x) + "S" for x in K.s])
523
+
524
+ fp.write(" ".join(blockStruct) + "\n")
525
+
526
+ # write b
527
+ fp.write(" ".join([accuracy % b2[i,0] for i in range(b2.shape[0])]) + "\n")
528
+
529
+ len_q = sum(K.q)
530
+ len_s = sum([x ** 2 for x in K.s])
531
+ # write c
532
+ if K.f > 0:
533
+ c_f = c2[0:K.f, :]
534
+ if K.l > 0:
535
+ c_l = c2[K.f:(K.f + K.l), :]
536
+ if len_q > 0:
537
+ c_q = c2[(K.f + K.l):(K.f + K.l + len_q), :]
538
+ if len_s > 0:
539
+ c_s = c2[(K.f + K.l + len_q):, :]
540
+
541
+ setBlock = 1
542
+ if K.f > 0:
543
+ list_row = [str(x + 1) for x in list(c_f.nonzero()[0])]
544
+ list_val = [accuracy % x for x in list(c_f.data)]
545
+ length = len(list_row)
546
+ for i in range(length):
547
+ fp.write(" ".join(("0", str(setBlock), list_row[i],
548
+ list_row[i], list_val[i])) + "\n")
549
+
550
+ setBlock += 1
551
+
552
+ if K.l > 0:
553
+ list_row = [str(x + 1) for x in list(c_l.nonzero()[0])]
554
+ list_val = [accuracy % x for x in list(c_l.data)]
555
+ length = len(list_row)
556
+ for i in range(length):
557
+ fp.write(" ".join(("0", str(setBlock), list_row[i],
558
+ list_row[i], list_val[i])) + "\n")
559
+
560
+ setBlock += 1
561
+
562
+ if len_q > 0:
563
+ offset = 0
564
+ for blockSize in K.q:
565
+ list_row = [str(x + 1) for x in
566
+ list(c_q[offset:(offset + blockSize), :].nonzero()[0])]
567
+ list_val = [accuracy % x for x in
568
+ list(c_q[offset:(offset + blockSize), :].data)]
569
+ length = len(list_row)
570
+ for i in range(length):
571
+ fp.write(" ".join(("0", str(setBlock), list_row[i],
572
+ list_row[i], list_val[i])) + "\n")
573
+
574
+ setBlock += 1
575
+ offset += blockSize
576
+
577
+ if len_s > 0:
578
+ offset = 0
579
+ for blockSize in K.s:
580
+ list_row = list(c_s[offset:(offset + blockSize * blockSize),
581
+ :].nonzero()[0])
582
+ list_val = [accuracy % x for x in
583
+ list(c_s[offset:(offset + blockSize * blockSize),
584
+ :].data)]
585
+ length = len(list_row)
586
+ for i in range(length):
587
+ setCol_row = (list_row[i] // blockSize) + 1
588
+ setCol_col = (list_row[i] % blockSize) + 1
589
+ if setCol_row <= setCol_col:
590
+ fp.write(" ".join(("0", str(setBlock), str(setCol_row),
591
+ str(setCol_col), list_val[i])) + "\n")
592
+
593
+ setBlock += 1
594
+ offset += blockSize * blockSize
595
+
596
+ # write A
597
+ if K.f > 0:
598
+ A_f = A2[:, 0:K.f]
599
+ if K.l > 0:
600
+ A_l = A2[:, K.f:(K.f + K.l)]
601
+ if len_q > 0:
602
+ A_q = A2[:, (K.f + K.l):(K.f + K.l + len_q)]
603
+ if len_s > 0:
604
+ A_s = A2[:, (K.f + K.l + len_q):]
605
+
606
+ setBlock = 1
607
+ if K.f > 0:
608
+ list_row = [str(x + 1) for x in list(A_f.nonzero()[0])]
609
+ list_col = [str(x + 1) for x in list(A_f.nonzero()[1])]
610
+ list_val = [accuracy % x for x in list(A_f.data)]
611
+ length = len(list_row)
612
+ for i in range(length):
613
+ fp.write(" ".join((list_row[i], str(setBlock), list_col[i],
614
+ list_col[i], list_val[i])) + "\n")
615
+
616
+ setBlock += 1
617
+
618
+ if K.l > 0:
619
+ list_row = [str(x + 1) for x in list(A_l.nonzero()[0])]
620
+ list_col = [str(x + 1) for x in list(A_l.nonzero()[1])]
621
+ list_val = [accuracy % x for x in list(A_l.data)]
622
+ length = len(list_row)
623
+ for i in range(length):
624
+ fp.write(" ".join((list_row[i], str(setBlock), list_col[i],
625
+ list_col[i], list_val[i])) + "\n")
626
+
627
+ setBlock += 1
628
+
629
+ if len_q > 0:
630
+ offset = 0
631
+ for blockSize in K.q:
632
+ list_row = [str(x + 1) for x in
633
+ list(A_q[:, offset:(offset + blockSize)].nonzero()[0])]
634
+ list_col = [str(x + 1) for x in
635
+ list(A_q[:, offset:(offset + blockSize)].nonzero()[1])]
636
+ list_val = [accuracy % x for x in
637
+ list(A_q[:, offset:(offset + blockSize)].data)]
638
+ length = len(list_row)
639
+ for i in range(length):
640
+ fp.write(" ".join((list_row[i], str(setBlock), list_col[i],
641
+ list_col[i], list_val[i])) + "\n")
642
+
643
+ setBlock += 1
644
+ offset += blockSize
645
+
646
+ if len_s > 0:
647
+ offset = 0
648
+ for blockSize in K.s:
649
+ list_row = [str(x + 1) for x in
650
+ list(A_s[:, offset:(offset + blockSize * blockSize)].
651
+ nonzero()[0])]
652
+ list_col = list(A_s[:, offset:(offset + blockSize * blockSize)].
653
+ nonzero()[1])
654
+ list_val = [accuracy % x for x in
655
+ list(A_s[:, offset:(offset + blockSize * blockSize)].
656
+ data)]
657
+ length = len(list_row)
658
+ for i in range(length):
659
+ setCol_row = (list_col[i] // blockSize) + 1
660
+ setCol_col = (list_col[i] % blockSize) + 1
661
+ if setCol_row <= setCol_col:
662
+ fp.write(" ".join((list_row[i], str(setBlock),
663
+ str(setCol_row), str(setCol_col),
664
+ list_val[i])) + "\n")
665
+
666
+ setBlock += 1
667
+ offset += blockSize * blockSize
668
+
669
+ fp.close()
670
+ return
671
+
672
+
673
+ # ==================================================
674
+ # Functions to write result file
675
+ # ==================================================
676
+ def write_version(fp):
677
+ """Write SDPAP title and version to file
678
+
679
+ Args:
680
+ fp: File pointer
681
+ """
682
+ fp.write("==================================================\n" +
683
+ " SDPAP: SDPA Python Interface\n" +
684
+ " SDPA group 2010-2011\n" +
685
+ "==================================================\n")
686
+ return
687
+
688
+ def write_parameter(fp, option):
689
+ """Write parameters to file
690
+
691
+ Args:
692
+ fp: File pointer
693
+ option: Parameters
694
+ """
695
+ fp.write("----- Parameters -----\n" +
696
+ 'maxIteration: ' + str(option['maxIteration']) + "\n" +
697
+ ' epsilonStar: ' + str(option['epsilonStar']) + "\n" +
698
+ ' lambdaStar: ' + str(option['lambdaStar']) + "\n" +
699
+ ' omegaStar: ' + str(option['omegaStar']) + "\n" +
700
+ ' lowerBound: ' + str(option['lowerBound']) + "\n" +
701
+ ' upperBound: ' + str(option['upperBound']) + "\n" +
702
+ ' betaStar: ' + str(option['betaStar']) + "\n" +
703
+ ' betaBar: ' + str(option['betaBar']) + "\n" +
704
+ ' gammaStar: ' + str(option['gammaStar']) + "\n" +
705
+ ' epsilonDash: ' + str(option['epsilonDash']) + "\n" +
706
+ ' isSymmetric: ' + str(option['isSymmetric']) + "\n" +
707
+ ' isDimacs: ' + str(option['isDimacs']) + "\n" +
708
+ ' xPrint: ' + str(option['xPrint']) + "\n" +
709
+ ' yPrint: ' + str(option['yPrint']) + "\n" +
710
+ ' sPrint: ' + str(option['sPrint']) + "\n" +
711
+ ' infPrint: ' + str(option['infPrint']) + "\n" +
712
+ ' print: ' + str(option['print']) + "\n" +
713
+ ' resultFile: ' + str(option['resultFile']) + "\n" +
714
+ ' sdpaResult: ' + str(option['sdpaResult']) + "\n" +
715
+ ' numThreads: ' + str(option['numThreads']) + "\n" +
716
+ ' frvMethod: ' + str(option['frvMethod']) + "\n" +
717
+ ' convMethod: ' + str(option['convMethod']) + "\n" +
718
+ 'domainMethod: ' + str(option['domainMethod']) + "\n" +
719
+ ' rangeMethod: ' + str(option['rangeMethod']) + "\n" +
720
+ ' rho: ' + str(option['rho']) + "\n" +
721
+ ' zeroPoint: ' + str(option['zeroPoint']) + "\n\n")
722
+
723
+ return
724
+
725
+ def write_symcone(fp, K, J=None):
726
+ """Write SymCone to file
727
+
728
+ Args:
729
+ fp: File pointer
730
+ K, J: SymCone
731
+ """
732
+ if J != None:
733
+ fp.write("K =\n" + str(K) + "J =\n" + str(J) + "\n")
734
+ else:
735
+ fp.write("K =\n" + str(K) + "\n")
736
+
737
+ return
738
+
739
+ def write_info(fp, sdpapinfo, sdpainfo, timeinfo):
740
+ """Write result info to file
741
+
742
+ Args:
743
+ fp: File pointer
744
+ sdpapinfo, sdpainfo, timeinfo: Result information
745
+ """
746
+ fp.write("----- Result -----\n" +
747
+ " SDPA.phase = %s\n" % sdpainfo['phasevalue'] +
748
+ " iteration = %d\n" % sdpainfo['iteration'] +
749
+ " primalObj = %+10.16e\n" % sdpapinfo['primalObj'] +
750
+ " dualObj = %+10.16e\n" % sdpapinfo['dualObj'] +
751
+ " dualityGap = %+10.16e\n" % sdpapinfo['dualityGap'] +
752
+ " primalError = %+10.16e\n" % sdpapinfo['primalError'] +
753
+ " dualError = %+10.16e\n" % sdpapinfo['dualError'] +
754
+ " convertTime = %f\n" % timeinfo['convert'] +
755
+ " solveTime = %f\n" % timeinfo['sdpa'] +
756
+ "retrievingTime = %f\n" % timeinfo['retrieve'] +
757
+ " totalTime = %f\n" % timeinfo['total'])
758
+
759
+ return
760
+
761
+ def write_result(fp, x, y):
762
+ """Write result x and y to file
763
+
764
+ Args:
765
+ fp: File pointer
766
+ x, y: results
767
+ """
768
+ if not sparse.isspmatrix_csc(x):
769
+ x = x.tocsc()
770
+ if not sparse.isspmatrix_csc(y):
771
+ y = y.tocsc()
772
+
773
+ x.sort_indices()
774
+ y.sort_indices()
775
+
776
+ fp.write("\nx(index, value) =\n")
777
+ writeStr = ''
778
+ count = 0
779
+ for (index, value) in zip(x.indices, x.data):
780
+ writeStr += "(%d: %+8.3e), " % (index, value)
781
+ if count == 4:
782
+ writeStr += "\n"
783
+ count = 0
784
+ else:
785
+ count += 1
786
+
787
+ fp.write(writeStr)
788
+
789
+ fp.write("\n\ny(index, value) =\n")
790
+ writeStr = ''
791
+ count = 0
792
+ for (index, value) in zip(y.indices, y.data):
793
+ writeStr += "(%d: %+8.3e), " % (index, value)
794
+ if count == 4:
795
+ writeStr += "\n"
796
+ count = 0
797
+ else:
798
+ count += 1
799
+
800
+
801
+ fp.write(writeStr)
802
+
803
+ return