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.
@@ -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
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))