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