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.
- sdpa_python-0.2.2.dist-info/LICENSE +339 -0
- sdpa_python-0.2.2.dist-info/METADATA +69 -0
- sdpa_python-0.2.2.dist-info/RECORD +24 -0
- sdpa_python-0.2.2.dist-info/WHEEL +5 -0
- sdpa_python-0.2.2.dist-info/top_level.txt +1 -0
- sdpap/__init__.py +28 -0
- sdpap/convert.py +348 -0
- sdpap/fileio.py +836 -0
- sdpap/fvelim/__init__.py +24 -0
- sdpap/fvelim/fvelim.py +256 -0
- sdpap/fvelim/fvelimext.cp313-win_amd64.pyd +0 -0
- sdpap/matdata.py +80 -0
- sdpap/param.py +366 -0
- sdpap/sdpacall/__init__.py +24 -0
- sdpap/sdpacall/sdpa.cp313-win_amd64.pyd +0 -0
- sdpap/sdpacall/sdpacall.py +71 -0
- sdpap/sdpap.py +450 -0
- sdpap/sdpaputils.py +140 -0
- sdpap/spcolo/__init__.py +26 -0
- sdpap/spcolo/asputils.py +182 -0
- sdpap/spcolo/clique.py +68 -0
- sdpap/spcolo/spcolo.py +356 -0
- sdpap/spcolo/spcoloext.cp313-win_amd64.pyd +0 -0
- sdpap/symcone.py +157 -0
sdpap/fvelim/__init__.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This file is a component of SDPAP
|
|
3
|
+
Copyright (C) 2010-2022 SDPA Project
|
|
4
|
+
|
|
5
|
+
This program is free software; you can redistribute it and/or modify
|
|
6
|
+
it under the terms of the GNU General Public License as published by
|
|
7
|
+
the Free Software Foundation; either version 2 of the License, or
|
|
8
|
+
(at your option) any later version.
|
|
9
|
+
|
|
10
|
+
This program is distributed in the hope that it will be useful,
|
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
GNU General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU General Public License along
|
|
16
|
+
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
17
|
+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
18
|
+
|
|
19
|
+
December 2010: Originally written by Kenta Kato
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from .fvelim import *
|
|
23
|
+
|
|
24
|
+
__all__ = filter(lambda s:not s.startswith('_'),dir())
|
sdpap/fvelim/fvelim.py
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
Eliminate free variables
|
|
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
|
+
December 2010: Originally written by Kenta Kato
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
__all__ = ['split', 'eliminate', 'result_split', 'result_elimination']
|
|
25
|
+
|
|
26
|
+
from . import fvelimext
|
|
27
|
+
from sdpap.symcone import SymCone
|
|
28
|
+
from sdpap.matdata import MatData
|
|
29
|
+
from scipy.sparse import csc_matrix, csr_matrix, bmat, eye
|
|
30
|
+
from scipy.sparse.linalg import spsolve
|
|
31
|
+
from scipy import sparse
|
|
32
|
+
from numpy import ones
|
|
33
|
+
|
|
34
|
+
def split(A, b, c, K, rho):
|
|
35
|
+
"""Eliminate free variables by Split method
|
|
36
|
+
Args:
|
|
37
|
+
A, b, c, K: SeDuMi format
|
|
38
|
+
rho: Parameter of range in split method or
|
|
39
|
+
pivoting in elimination method
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Converted problem (A2, b2, c2, K2).
|
|
43
|
+
"""
|
|
44
|
+
# --------------------------------------------------
|
|
45
|
+
# Type check
|
|
46
|
+
# --------------------------------------------------
|
|
47
|
+
if not sparse.isspmatrix_csc(A):
|
|
48
|
+
A = A.tocsc()
|
|
49
|
+
if not sparse.isspmatrix_csc(b):
|
|
50
|
+
b = b.tocsc()
|
|
51
|
+
if not sparse.isspmatrix_csc(c):
|
|
52
|
+
c = c.tocsc()
|
|
53
|
+
|
|
54
|
+
# --------------------------------------------------
|
|
55
|
+
# Get K.f part
|
|
56
|
+
# --------------------------------------------------
|
|
57
|
+
A_f = A[:, 0:K.f]
|
|
58
|
+
A_lqs = A[:, K.f:]
|
|
59
|
+
c_f = c[0:K.f, :]
|
|
60
|
+
c_lqs = c[K.f:, :]
|
|
61
|
+
|
|
62
|
+
# ----------------------------------------
|
|
63
|
+
# Split method
|
|
64
|
+
# ----------------------------------------
|
|
65
|
+
c_fp = c_f + csc_matrix(ones((c_f.shape[0], 1))) * rho
|
|
66
|
+
c_fm = -c_f + csc_matrix(ones((c_f.shape[0], 1))) * rho
|
|
67
|
+
A_fp = A_f
|
|
68
|
+
A_fm = -A_f
|
|
69
|
+
A2 = bmat([[A_fp, A_fm, A_lqs]])
|
|
70
|
+
b2 = b
|
|
71
|
+
c2 = bmat([[c_fp],
|
|
72
|
+
[c_fm],
|
|
73
|
+
[c_lqs]])
|
|
74
|
+
K2 = SymCone(f=0, l=2*K.f+K.l, q=K.q, s=K.s)
|
|
75
|
+
|
|
76
|
+
return A2, b2, c2, K2
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def eliminate(A, b, c, K, rho, zeroPoint):
|
|
80
|
+
"""Eliminate free variables by Elimination method
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
A, b, c, K: SeDuMi format
|
|
84
|
+
rho: Parameter of range in split method or
|
|
85
|
+
pivoting in elimination method
|
|
86
|
+
zeroPoint: The zero point of matrix operation
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
A Tuple (A2, b2, c2, K2, LiP, U, Q, LPA_B, LPb_B, cfQU, gamma).
|
|
90
|
+
Each members are:
|
|
91
|
+
A2, b2, c2, K2: Converted Problem
|
|
92
|
+
LiP, U, Q, LPA_B, LPb_B, cfQU: For retrieving results.
|
|
93
|
+
If method=='split', these value is None.
|
|
94
|
+
gamma: Constant of objective value.
|
|
95
|
+
If method=='split', gamma = 0.
|
|
96
|
+
rank_Af: Matrix rank of K.f part of A
|
|
97
|
+
"""
|
|
98
|
+
# --------------------------------------------------
|
|
99
|
+
# Type check
|
|
100
|
+
# --------------------------------------------------
|
|
101
|
+
if not sparse.isspmatrix_csc(A):
|
|
102
|
+
A = A.tocsc()
|
|
103
|
+
if not sparse.isspmatrix_csc(b):
|
|
104
|
+
b = b.tocsc()
|
|
105
|
+
if not sparse.isspmatrix_csc(c):
|
|
106
|
+
c = c.tocsc()
|
|
107
|
+
|
|
108
|
+
# --------------------------------------------------
|
|
109
|
+
# Get K.f part
|
|
110
|
+
# --------------------------------------------------
|
|
111
|
+
A_f = A[:, 0:K.f]
|
|
112
|
+
A_lqs = A[:, K.f:]
|
|
113
|
+
c_f = c[0:K.f, :]
|
|
114
|
+
c_lqs = c[K.f:, :]
|
|
115
|
+
|
|
116
|
+
# ----------------------------------------
|
|
117
|
+
# Elimination method
|
|
118
|
+
# ----------------------------------------
|
|
119
|
+
if not sparse.isspmatrix_csc(A_f):
|
|
120
|
+
A_f = A_f.tocsc()
|
|
121
|
+
if not sparse.isspmatrix_csc(A_lqs):
|
|
122
|
+
A_lqs = A_lqs.tocsc()
|
|
123
|
+
|
|
124
|
+
A_f.sort_indices()
|
|
125
|
+
A_lqs.sort_indices()
|
|
126
|
+
data_Af = MatData(A_f)
|
|
127
|
+
data_Alqs = MatData(A_lqs)
|
|
128
|
+
data_LiP, data_U, data_V, Q, rank_Af = \
|
|
129
|
+
fvelimext.lu(data_Af, data_Alqs, rho, zeroPoint)
|
|
130
|
+
LiP = MatData(values=data_LiP[0],
|
|
131
|
+
rowind=data_LiP[1],
|
|
132
|
+
colptr=data_LiP[2],
|
|
133
|
+
size=(A_f.shape[0], A_f.shape[0])).tomatrix()
|
|
134
|
+
U = MatData(values=data_U[0],
|
|
135
|
+
rowind=data_U[1],
|
|
136
|
+
colptr=data_U[2],
|
|
137
|
+
size=(rank_Af, rank_Af)).tomatrix()
|
|
138
|
+
if data_V != None:
|
|
139
|
+
V = MatData(values=data_V[0],
|
|
140
|
+
rowind=data_V[1],
|
|
141
|
+
colptr=data_V[2],
|
|
142
|
+
size=(rank_Af, K.f - rank_Af)).tomatrix()
|
|
143
|
+
|
|
144
|
+
# Make LPA, LPb
|
|
145
|
+
LPA = LiP * A_lqs
|
|
146
|
+
LPb = LiP * b
|
|
147
|
+
|
|
148
|
+
# Devide to Basis and Nonbasis
|
|
149
|
+
LPA_B = LPA[0:rank_Af, :]
|
|
150
|
+
A2 = LPA[rank_Af:, :]
|
|
151
|
+
LPb_B = LPb[0:rank_Af, :]
|
|
152
|
+
b2 = LPb[rank_Af:, :]
|
|
153
|
+
|
|
154
|
+
ordering = range(K.f)
|
|
155
|
+
for i, index in enumerate(Q):
|
|
156
|
+
tmp = ordering[i]
|
|
157
|
+
ordering[i] = ordering[index]
|
|
158
|
+
ordering[index] = tmp
|
|
159
|
+
|
|
160
|
+
# Convert objective function
|
|
161
|
+
cfQ = c_f[ordering]
|
|
162
|
+
|
|
163
|
+
# Linear dependent case
|
|
164
|
+
if rank_Af < K.f:
|
|
165
|
+
cfQ1 = cfQ[0:rank_Af, :]
|
|
166
|
+
cfQ2 = cfQ[rank_Af:, :]
|
|
167
|
+
cfQ = cfQ1
|
|
168
|
+
|
|
169
|
+
cfQU = csr_matrix(spsolve(U.T, cfQ))
|
|
170
|
+
|
|
171
|
+
# Unbound check
|
|
172
|
+
# Linear dependent case
|
|
173
|
+
if rank_Af < K.f:
|
|
174
|
+
cfQUV = cfQU * V
|
|
175
|
+
submat = cfQ2 - cfQUV.T
|
|
176
|
+
if submat.nnz > 0 and max(abs(submat.data)) > zeroPoint:
|
|
177
|
+
print("%.15e" % max(abs(submat.data)))
|
|
178
|
+
raise ValueError("This problem is unbound")
|
|
179
|
+
|
|
180
|
+
cfQUA_B = cfQU * LPA_B
|
|
181
|
+
c2 = c_lqs - cfQUA_B.T
|
|
182
|
+
|
|
183
|
+
# Get gamma
|
|
184
|
+
gamma = (cfQU * LPb_B).todense()[0,0]
|
|
185
|
+
print("gamma = %f" % gamma)
|
|
186
|
+
|
|
187
|
+
# Make K2
|
|
188
|
+
K2 = SymCone(f=0, l=K.l, q=K.q, s=K.s)
|
|
189
|
+
|
|
190
|
+
return A2, b2, c2, K2, LiP, U, Q, LPA_B, LPb_B, cfQU, gamma, rank_Af
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def result_split(x2, y2, s2, K):
|
|
194
|
+
"""Get result of problem with free variables by Split method
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
x2, y2, s2: SDPA result
|
|
198
|
+
K: SymCone of original problem
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
Result of original problem (x, y, s)
|
|
202
|
+
"""
|
|
203
|
+
x_fp = x2[0:K.f, :]
|
|
204
|
+
x_fm = x2[K.f:(K.f + K.f), :]
|
|
205
|
+
x_lqs = x2[(K.f + K.f):, :]
|
|
206
|
+
x_f = x_fp - x_fm
|
|
207
|
+
x = bmat([[x_f],
|
|
208
|
+
[x_lqs]])
|
|
209
|
+
|
|
210
|
+
s_lqs = s2[(K.f + K.f):, :]
|
|
211
|
+
s = bmat([[csc_matrix((K.f, 1))],
|
|
212
|
+
[s_lqs]])
|
|
213
|
+
|
|
214
|
+
y = y2
|
|
215
|
+
|
|
216
|
+
return x, y, s
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def result_elimination(x2, y2, s2, K, LiP, U, Q, LPA_B, LPb_B, cfQU, rank_Af):
|
|
220
|
+
"""Get result of problem with free variables by Elimination method
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
x2, y2, s2: SDPA result
|
|
224
|
+
K: SymCone of original problem
|
|
225
|
+
LiP, U, Q, LPA_B, LPb_B, cfQU, rank_Af: Informations of LU factorization
|
|
226
|
+
|
|
227
|
+
Returns:
|
|
228
|
+
Result of original problem (x, y, s)
|
|
229
|
+
"""
|
|
230
|
+
import copy
|
|
231
|
+
bAx = LPb_B - (LPA_B * x2)
|
|
232
|
+
UbAx = csr_matrix(spsolve(U, bAx)).T
|
|
233
|
+
Qr = copy.deepcopy(Q)
|
|
234
|
+
Qr.reverse()
|
|
235
|
+
|
|
236
|
+
ordering = range(K.f)
|
|
237
|
+
for i, index in enumerate(Qr):
|
|
238
|
+
tmp = ordering[rank_Af - i - 1]
|
|
239
|
+
ordering[rank_Af - i - 1] = ordering[index]
|
|
240
|
+
ordering[index] = tmp
|
|
241
|
+
|
|
242
|
+
# Linear dependent case
|
|
243
|
+
if rank_Af < K.f:
|
|
244
|
+
UbAx = bmat([[UbAx],
|
|
245
|
+
[csc_matrix((K.f - rank_Af, 1))]]).tocsc()
|
|
246
|
+
|
|
247
|
+
x_f = UbAx[ordering]
|
|
248
|
+
x = bmat([[x_f],
|
|
249
|
+
[x2]])
|
|
250
|
+
|
|
251
|
+
y = (bmat([[cfQU, y2.T]]) * LiP).T
|
|
252
|
+
|
|
253
|
+
s = bmat([[csc_matrix((K.f, 1))],
|
|
254
|
+
[s2]])
|
|
255
|
+
|
|
256
|
+
return x, y, s
|
|
Binary file
|
sdpap/matdata.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
Class definition of MatData (used as interface between SciPy and SDPA C API)
|
|
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
|
+
December 2010: Originally written by Kenta Kato
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from scipy import sparse
|
|
25
|
+
from numpy import array
|
|
26
|
+
|
|
27
|
+
class MatData(object):
|
|
28
|
+
"""Description of a sparse matrix
|
|
29
|
+
|
|
30
|
+
Attributes:
|
|
31
|
+
size_row: Size of row
|
|
32
|
+
size_col: Size of column
|
|
33
|
+
values: List of Values
|
|
34
|
+
rowind: List of row indices
|
|
35
|
+
colptr: List of start index of each column
|
|
36
|
+
"""
|
|
37
|
+
def __init__(self, mat=None,
|
|
38
|
+
values=None, rowind=None, colptr=None, size=None):
|
|
39
|
+
"""Constructor for sparse matrix
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
mat: input sparse matrix
|
|
43
|
+
values: List of Values
|
|
44
|
+
rowind: List of row indices
|
|
45
|
+
colptr: List of start index of each column
|
|
46
|
+
size: Tuple (size_row, size_col)
|
|
47
|
+
"""
|
|
48
|
+
if sparse.issparse(mat):
|
|
49
|
+
mat2 = mat.tocsc() if not sparse.isspmatrix_csc(mat) else mat
|
|
50
|
+
self.size_row, self.size_col = mat2.shape
|
|
51
|
+
self.values = list(mat2.data)
|
|
52
|
+
self.rowind = list(mat2.indices)
|
|
53
|
+
self.colptr = list(mat2.indptr)
|
|
54
|
+
elif (isinstance(values, list) and isinstance(rowind, list) and
|
|
55
|
+
isinstance(colptr, list) and isinstance(size, tuple)):
|
|
56
|
+
if (len(values) != len(rowind) or len(colptr) != size[1] + 1):
|
|
57
|
+
raise ValueError('size of val, row, col list must be same')
|
|
58
|
+
self.size_row, self.size_col = size
|
|
59
|
+
self.values, self.rowind, self.colptr = values, rowind, colptr
|
|
60
|
+
else:
|
|
61
|
+
raise TypeError('Input arg must be sparse matrix or lists.')
|
|
62
|
+
|
|
63
|
+
def __len__(self):
|
|
64
|
+
"""Return num of nonzero elements in matrix"""
|
|
65
|
+
return len(self.values)
|
|
66
|
+
|
|
67
|
+
def size(self):
|
|
68
|
+
"""Return the size of matrix"""
|
|
69
|
+
return (self.size_row, self.size_col)
|
|
70
|
+
|
|
71
|
+
def tomatrix(self):
|
|
72
|
+
"""Get sparse matrix from self
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Sparse Matrix in lil_matrix format
|
|
76
|
+
"""
|
|
77
|
+
return sparse.csc_matrix((array(self.values),
|
|
78
|
+
array(self.rowind),
|
|
79
|
+
array(self.colptr)),
|
|
80
|
+
shape=(self.size_row, self.size_col))
|