qoro-divi 0.2.0b1__py3-none-any.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.
Files changed (58) hide show
  1. divi/__init__.py +8 -0
  2. divi/_pbar.py +73 -0
  3. divi/circuits.py +139 -0
  4. divi/exp/cirq/__init__.py +7 -0
  5. divi/exp/cirq/_lexer.py +126 -0
  6. divi/exp/cirq/_parser.py +889 -0
  7. divi/exp/cirq/_qasm_export.py +37 -0
  8. divi/exp/cirq/_qasm_import.py +35 -0
  9. divi/exp/cirq/exception.py +21 -0
  10. divi/exp/scipy/_cobyla.py +342 -0
  11. divi/exp/scipy/pyprima/LICENCE.txt +28 -0
  12. divi/exp/scipy/pyprima/__init__.py +263 -0
  13. divi/exp/scipy/pyprima/cobyla/__init__.py +0 -0
  14. divi/exp/scipy/pyprima/cobyla/cobyla.py +599 -0
  15. divi/exp/scipy/pyprima/cobyla/cobylb.py +849 -0
  16. divi/exp/scipy/pyprima/cobyla/geometry.py +240 -0
  17. divi/exp/scipy/pyprima/cobyla/initialize.py +269 -0
  18. divi/exp/scipy/pyprima/cobyla/trustregion.py +540 -0
  19. divi/exp/scipy/pyprima/cobyla/update.py +331 -0
  20. divi/exp/scipy/pyprima/common/__init__.py +0 -0
  21. divi/exp/scipy/pyprima/common/_bounds.py +41 -0
  22. divi/exp/scipy/pyprima/common/_linear_constraints.py +46 -0
  23. divi/exp/scipy/pyprima/common/_nonlinear_constraints.py +64 -0
  24. divi/exp/scipy/pyprima/common/_project.py +224 -0
  25. divi/exp/scipy/pyprima/common/checkbreak.py +107 -0
  26. divi/exp/scipy/pyprima/common/consts.py +48 -0
  27. divi/exp/scipy/pyprima/common/evaluate.py +101 -0
  28. divi/exp/scipy/pyprima/common/history.py +39 -0
  29. divi/exp/scipy/pyprima/common/infos.py +30 -0
  30. divi/exp/scipy/pyprima/common/linalg.py +452 -0
  31. divi/exp/scipy/pyprima/common/message.py +336 -0
  32. divi/exp/scipy/pyprima/common/powalg.py +131 -0
  33. divi/exp/scipy/pyprima/common/preproc.py +393 -0
  34. divi/exp/scipy/pyprima/common/present.py +5 -0
  35. divi/exp/scipy/pyprima/common/ratio.py +56 -0
  36. divi/exp/scipy/pyprima/common/redrho.py +49 -0
  37. divi/exp/scipy/pyprima/common/selectx.py +346 -0
  38. divi/interfaces.py +25 -0
  39. divi/parallel_simulator.py +258 -0
  40. divi/qasm.py +220 -0
  41. divi/qem.py +191 -0
  42. divi/qlogger.py +119 -0
  43. divi/qoro_service.py +343 -0
  44. divi/qprog/__init__.py +13 -0
  45. divi/qprog/_graph_partitioning.py +619 -0
  46. divi/qprog/_mlae.py +182 -0
  47. divi/qprog/_qaoa.py +440 -0
  48. divi/qprog/_vqe.py +275 -0
  49. divi/qprog/_vqe_sweep.py +144 -0
  50. divi/qprog/batch.py +235 -0
  51. divi/qprog/optimizers.py +75 -0
  52. divi/qprog/quantum_program.py +493 -0
  53. divi/utils.py +116 -0
  54. qoro_divi-0.2.0b1.dist-info/LICENSE +190 -0
  55. qoro_divi-0.2.0b1.dist-info/LICENSES/Apache-2.0.txt +73 -0
  56. qoro_divi-0.2.0b1.dist-info/METADATA +57 -0
  57. qoro_divi-0.2.0b1.dist-info/RECORD +58 -0
  58. qoro_divi-0.2.0b1.dist-info/WHEEL +4 -0
@@ -0,0 +1,240 @@
1
+ """
2
+ This module contains subroutines concerning the geometry-improving of the interpolation set.
3
+
4
+ Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA.
5
+
6
+ Dedicated to late Professor M. J. D. Powell FRS (1936--2015).
7
+
8
+ Python translation by Nickolai Belakovski.
9
+ """
10
+
11
+ import numpy as np
12
+
13
+ from ..common.consts import DEBUGGING
14
+ from ..common.linalg import inprod, isinv, matprod, norm, primapow2, primasum
15
+
16
+
17
+ def setdrop_tr(ximproved, d, delta, rho, sim, simi):
18
+ """
19
+ This function finds (the index) of a current interpolation point to be replaced with
20
+ the trust-region trial point. See (19)-(22) of the COBYLA paper.
21
+ N.B.:
22
+ 1. If XIMPROVED == True, then JDROP > 0 so that D is included into XPT. Otherwise,
23
+ it is a bug.
24
+ 2. COBYLA never sets JDROP = NUM_VARS
25
+ TODO: Check whether it improves the performance if JDROP = NUM_VARS is allowed when
26
+ XIMPROVED is True. Note that UPDATEXFC should be revised accordingly.
27
+ """
28
+
29
+ # Local variables
30
+ itol = 0.1
31
+
32
+ # Sizes
33
+ num_vars = np.size(sim, 0)
34
+
35
+ # Preconditions
36
+ if DEBUGGING:
37
+ assert num_vars >= 1
38
+ assert np.size(d) == num_vars and all(np.isfinite(d))
39
+ assert delta >= rho and rho > 0
40
+ assert np.size(sim, 0) == num_vars and np.size(sim, 1) == num_vars + 1
41
+ assert np.isfinite(sim).all()
42
+ assert all(np.max(abs(sim[:, :num_vars]), axis=0) > 0)
43
+ assert np.size(simi, 0) == num_vars and np.size(simi, 1) == num_vars
44
+ assert np.isfinite(simi).all()
45
+ assert isinv(sim[:, :num_vars], simi, itol)
46
+
47
+ # ====================#
48
+ # Calculation starts #
49
+ # ====================#
50
+
51
+ # -------------------------------------------------------------------------------------------------- #
52
+ # The following code is Powell's scheme for defining JDROP.
53
+ # -------------------------------------------------------------------------------------------------- #
54
+ # ! JDROP = 0 by default. It cannot be removed, as JDROP may not be set below in some cases (e.g.,
55
+ # ! when XIMPROVED == FALSE, MAXVAL(ABS(SIMID)) <= 1, and MAXVAL(VETA) <= EDGMAX).
56
+ # jdrop = 0
57
+ #
58
+ # ! SIMID(J) is the value of the J-th Lagrange function at D. It is the counterpart of VLAG in UOBYQA
59
+ # ! and DEN in NEWUOA/BOBYQA/LINCOA, but it excludes the value of the (N+1)-th Lagrange function.
60
+ # simid = matprod(simi, d)
61
+ # if (any(abs(simid) > 1) .or. (ximproved .and. any(.not. is_nan(simid)))) then
62
+ # jdrop = int(maxloc(abs(simid), mask=(.not. is_nan(simid)), dim=1), kind(jdrop))
63
+ # !!MATLAB: [~, jdrop] = max(simid, [], 'omitnan');
64
+ # end if
65
+ #
66
+ # ! VETA(J) is the distance from the J-th vertex of the simplex to the best vertex, taking the trial
67
+ # ! point SIM(:, N+1) + D into account.
68
+ # if (ximproved) then
69
+ # veta = sqrt(sum((sim(:, 1:n) - spread(d, dim=2, ncopies=n))**2, dim=1))
70
+ # !!MATLAB: veta = sqrt(sum((sim(:, 1:n) - d).^2)); % d should be a column! Implicit expansion
71
+ # else
72
+ # veta = sqrt(sum(sim(:, 1:n)**2, dim=1))
73
+ # end if
74
+ #
75
+ # ! VSIG(J) (J=1, .., N) is the Euclidean distance from vertex J to the opposite face of the simplex.
76
+ # vsig = ONE / sqrt(sum(simi**2, dim=2))
77
+ # sigbar = abs(simid) * vsig
78
+ #
79
+ # ! The following JDROP will overwrite the previous one if its premise holds.
80
+ # mask = (veta > factor_delta * delta .and. (sigbar >= factor_alpha * delta .or. sigbar >= vsig))
81
+ # if (any(mask)) then
82
+ # jdrop = int(maxloc(veta, mask=mask, dim=1), kind(jdrop))
83
+ # !!MATLAB: etamax = max(veta(mask)); jdrop = find(mask & ~(veta < etamax), 1, 'first');
84
+ # end if
85
+ #
86
+ # ! Powell's code does not include the following instructions. With Powell's code, if SIMID consists
87
+ # ! of only NaN, then JDROP can be 0 even when XIMPROVED == TRUE (i.e., D reduces the merit function).
88
+ # ! With the following code, JDROP cannot be 0 when XIMPROVED == TRUE, unless VETA is all NaN, which
89
+ # ! should not happen if X0 does not contain NaN, the trust-region/geometry steps never contain NaN,
90
+ # ! and we exit once encountering an iterate containing Inf (due to overflow).
91
+ # if (ximproved .and. jdrop <= 0) then ! Write JDROP <= 0 instead of JDROP == 0 for robustness.
92
+ # jdrop = int(maxloc(veta, mask=(.not. is_nan(veta)), dim=1), kind(jdrop))
93
+ # !!MATLAB: [~, jdrop] = max(veta, [], 'omitnan');
94
+ # end if
95
+ # -------------------------------------------------------------------------------------------------- #
96
+ # Powell's scheme ends here.
97
+ # -------------------------------------------------------------------------------------------------- #
98
+
99
+ # The following definition of JDROP is inspired by SETDROP_TR in UOBYQA/NEWUOA/BOBYQA/LINCOA.
100
+ # It is simpler and works better than Powell's scheme. Note that we allow JDROP to be NUM_VARS+1 if
101
+ # XIMPROVED is True, whereas Powell's code does not.
102
+ # See also (4.1) of Scheinberg-Toint-2010: Self-Correcting Geometry in Model-Based Algorithms for
103
+ # Derivative-Free Unconstrained Optimization, which refers to the strategy here as the "combined
104
+ # distance/poisedness criteria".
105
+
106
+ # DISTSQ[j] is the square of the distance from the jth vertex of the simplex to get "best" point so
107
+ # far, taking the trial point SIM[:, NUM_VARS] + D into account.
108
+ distsq = np.zeros(np.size(sim, 1))
109
+ if ximproved:
110
+ distsq[:num_vars] = primasum(
111
+ primapow2(sim[:, :num_vars] - np.tile(d, (num_vars, 1)).T), axis=0
112
+ )
113
+ distsq[num_vars] = primasum(d * d)
114
+ else:
115
+ distsq[:num_vars] = primasum(primapow2(sim[:, :num_vars]), axis=0)
116
+ distsq[num_vars] = 0
117
+
118
+ weight = np.maximum(
119
+ 1, distsq / primapow2(np.maximum(rho, delta / 10))
120
+ ) # Similar to Powell's NEWUOA code.
121
+
122
+ # Other possible definitions of weight. They work almost the same as the one above.
123
+ # weight = distsq # Similar to Powell's LINCOA code, but WRONG. See comments in LINCOA/geometry.f90.
124
+ # weight = max(1, max(25 * distsq / delta**2)) # Similar to Powell's BOBYQA code, works well.
125
+ # weight = max(1, max(10 * distsq / delta**2))
126
+ # weight = max(1, max(1e2 * distsq / delta**2))
127
+ # weight = max(1, max(distsq / rho**2)) ! Similar to Powell's UOBYQA
128
+
129
+ # If 0 <= j < NUM_VARS, SIMID[j] is the value of the jth Lagrange function at D; the value of the
130
+ # (NUM_VARS+1)th Lagrange function is 1 - sum(SIMID). [SIMID, 1 - sum(SIMID)] is the counterpart of
131
+ # VLAG in UOBYQA and DEN in NEWUOA/BOBYQA/LINCOA.
132
+ simid = matprod(simi, d)
133
+ score = weight * abs(np.array([*simid, 1 - primasum(simid)]))
134
+
135
+ # If XIMPROVED = False (D does not render a better X), set SCORE[NUM_VARS] = -1 to avoid JDROP = NUM_VARS.
136
+ if not ximproved:
137
+ score[num_vars] = -1
138
+
139
+ # score[j] is NaN implies SIMID[j] is NaN, but we want abs(SIMID) to be big. So we
140
+ # exclude such j.
141
+ score[np.isnan(score)] = -1
142
+
143
+ jdrop = None
144
+ # The following if statement works a bit better than
145
+ # `if any(score > 1) or (any(score > 0) and ximproved)` from Powell's UOBYQA and
146
+ # NEWUOA code.
147
+ if any(score > 0): # Powell's BOBYQA and LINCOA code.
148
+ jdrop = np.argmax(score)
149
+
150
+ if ximproved and jdrop is None:
151
+ jdrop = np.argmax(distsq)
152
+
153
+ # ==================#
154
+ # Calculation ends #
155
+ # ==================#
156
+
157
+ # Postconditions
158
+ if DEBUGGING:
159
+ assert jdrop is None or (0 <= jdrop < num_vars + 1)
160
+ assert jdrop <= num_vars or ximproved
161
+ assert jdrop >= 0 or not ximproved
162
+ # JDROP >= 1 when XIMPROVED = TRUE unless NaN occurs in DISTSQ, which should not happen if the
163
+ # starting point does not contain NaN and the trust-region/geometry steps never contain NaN.
164
+
165
+ return jdrop
166
+
167
+
168
+ def geostep(jdrop, amat, bvec, conmat, cpen, cval, delbar, fval, simi):
169
+ """
170
+ This function calculates a geometry step so that the geometry of the interpolation set is improved
171
+ when SIM[: JDROP_GEO] is replaced with SIM[:, NUM_VARS] + D. See (15)--(17) of the COBYLA paper.
172
+ """
173
+
174
+ # Sizes
175
+ m_lcon = np.size(bvec, 0) if bvec is not None else 0
176
+ num_constraints = np.size(conmat, 0)
177
+ num_vars = np.size(simi, 0)
178
+
179
+ # Preconditions
180
+ if DEBUGGING:
181
+ assert num_constraints >= m_lcon >= 0
182
+ assert num_vars >= 1
183
+ assert delbar > 0
184
+ assert cpen > 0
185
+ assert np.size(simi, 0) == num_vars and np.size(simi, 1) == num_vars
186
+ assert np.isfinite(simi).all()
187
+ assert np.size(fval) == num_vars + 1 and not any(
188
+ np.isnan(fval) | np.isposinf(fval)
189
+ )
190
+ assert (
191
+ np.size(conmat, 0) == num_constraints and np.size(conmat, 1) == num_vars + 1
192
+ )
193
+ assert not np.any(np.isnan(conmat) | np.isposinf(conmat))
194
+ assert np.size(cval) == num_vars + 1 and not any(
195
+ cval < 0 | np.isnan(cval) | np.isposinf(cval)
196
+ )
197
+ assert 0 <= jdrop < num_vars
198
+
199
+ # ====================#
200
+ # Calculation starts #
201
+ # ====================#
202
+
203
+ # SIMI[JDROP, :] is a vector perpendicular to the face of the simplex to the opposite of vertex
204
+ # JDROP. Set D to the vector in this direction and with length DELBAR.
205
+ d = simi[jdrop, :]
206
+ d = delbar * (d / norm(d))
207
+
208
+ # The code below chooses the direction of D according to an approximation of the merit function.
209
+ # See (17) of the COBYLA paper and line 225 of Powell's cobylb.f.
210
+
211
+ # Calculate the coefficients of the linear approximations to the objective and constraint functions.
212
+ # N.B.: CONMAT and SIMI have been updated after the last trust-region step, but G and A have not.
213
+ # So we cannot pass G and A from outside.
214
+ g = matprod(fval[:num_vars] - fval[num_vars], simi)
215
+ A = np.zeros((num_vars, num_constraints))
216
+ A[:, :m_lcon] = amat.T if amat is not None else amat
217
+ A[:, m_lcon:] = matprod(
218
+ (
219
+ conmat[m_lcon:, :num_vars]
220
+ - np.tile(conmat[m_lcon:, num_vars], (num_vars, 1)).T
221
+ ),
222
+ simi,
223
+ ).T
224
+ # CVPD and CVND are the predicted constraint violation of D and -D by the linear models.
225
+ cvpd = np.max(np.append(0, conmat[:, num_vars] + matprod(d, A)))
226
+ cvnd = np.max(np.append(0, conmat[:, num_vars] - matprod(d, A)))
227
+ if -inprod(d, g) + cpen * cvnd < inprod(d, g) + cpen * cvpd:
228
+ d *= -1
229
+
230
+ # ==================#
231
+ # Calculation ends #
232
+ # ==================#
233
+
234
+ # Postconditions
235
+ if DEBUGGING:
236
+ assert np.size(d) == num_vars and all(np.isfinite(d))
237
+ # In theory, ||S|| == DELBAR, which may be false due to rounding, but not too far.
238
+ # It is crucial to ensure that the geometry step is nonzero, which holds in theory.
239
+ assert 0.9 * delbar < np.linalg.norm(d) <= 1.1 * delbar
240
+ return d
@@ -0,0 +1,269 @@
1
+ """
2
+ This module contains subroutines for initialization.
3
+
4
+ Translated from Zaikun Zhang's modern-Fortran reference implementation in PRIMA.
5
+
6
+ Dedicated to late Professor M. J. D. Powell FRS (1936--2015).
7
+
8
+ Python translation by Nickolai Belakovski.
9
+ """
10
+
11
+ import numpy as np
12
+
13
+ from ..common.checkbreak import checkbreak_con
14
+ from ..common.consts import DEBUGGING, REALMAX
15
+ from ..common.evaluate import evaluate
16
+ from ..common.history import savehist
17
+ from ..common.infos import INFO_DEFAULT
18
+ from ..common.linalg import inv
19
+ from ..common.message import fmsg
20
+ from ..common.selectx import savefilt
21
+
22
+
23
+ def initxfc(
24
+ calcfc,
25
+ iprint,
26
+ maxfun,
27
+ constr0,
28
+ amat,
29
+ bvec,
30
+ ctol,
31
+ f0,
32
+ ftarget,
33
+ rhobeg,
34
+ x0,
35
+ xhist,
36
+ fhist,
37
+ chist,
38
+ conhist,
39
+ maxhist,
40
+ ):
41
+ """
42
+ This subroutine does the initialization concerning X, function values, and
43
+ constraints.
44
+ """
45
+
46
+ # Local variables
47
+ solver = "COBYLA"
48
+ srname = "INITIALIZE"
49
+
50
+ # Sizes
51
+ num_constraints = np.size(constr0)
52
+ m_lcon = np.size(bvec) if bvec is not None else 0
53
+ m_nlcon = num_constraints - m_lcon
54
+ num_vars = np.size(x0)
55
+
56
+ # Preconditions
57
+ if DEBUGGING:
58
+ assert num_constraints >= 0, f"M >= 0 {srname}"
59
+ assert num_vars >= 1, f"N >= 1 {srname}"
60
+ assert abs(iprint) <= 3, f"IPRINT is 0, 1, -1, 2, -2, 3, or -3 {srname}"
61
+ # assert conmat.shape == (num_constraints , num_vars + 1), f'CONMAT.shape = [M, N+1] {srname}'
62
+ # assert cval.size == num_vars + 1, f'CVAL.size == N+1 {srname}'
63
+ # assert maxchist * (maxchist - maxhist) == 0, f'CHIST.shape == 0 or MAXHIST {srname}'
64
+ # assert conhist.shape[0] == num_constraints and maxconhist * (maxconhist - maxhist) == 0, 'CONHIST.shape[0] == num_constraints, SIZE(CONHIST, 2) == 0 or MAXHIST {srname)}'
65
+ # assert maxfhist * (maxfhist - maxhist) == 0, f'FHIST.shape == 0 or MAXHIST {srname}'
66
+ # assert xhist.shape[0] == num_vars and maxxhist * (maxxhist - maxhist) == 0, 'XHIST.shape[0] == N, SIZE(XHIST, 2) == 0 or MAXHIST {srname)}'
67
+ assert all(np.isfinite(x0)), f"X0 is finite {srname}"
68
+ assert rhobeg > 0, f"RHOBEG > 0 {srname}"
69
+
70
+ # ====================#
71
+ # Calculation starts #
72
+ # ====================#
73
+
74
+ # Initialize info to the default value. At return, a value different from this
75
+ # value will indicate an abnormal return
76
+ info = INFO_DEFAULT
77
+
78
+ # Initialize the simplex. It will be revised during the initialization.
79
+ sim = np.eye(num_vars, num_vars + 1) * rhobeg
80
+ sim[:, num_vars] = x0
81
+
82
+ # Initialize the matrix simi. In most cases simi is overwritten, but not always.
83
+ simi = np.eye(num_vars) / rhobeg
84
+
85
+ # evaluated[j] = True iff the function/constraint of SIM[:, j] has been evaluated.
86
+ evaluated = np.zeros(num_vars + 1, dtype=bool)
87
+
88
+ # Initialize fval
89
+ fval = np.zeros(num_vars + 1) + REALMAX
90
+ cval = np.zeros(num_vars + 1) + REALMAX
91
+ conmat = np.zeros((num_constraints, num_vars + 1)) + REALMAX
92
+
93
+ for k in range(num_vars + 1):
94
+ x = sim[:, num_vars].copy()
95
+ # We will evaluate F corresponding to SIM(:, J).
96
+ if k == 0:
97
+ j = num_vars
98
+ f = f0
99
+ constr = constr0
100
+ else:
101
+ j = k - 1
102
+ x[j] += rhobeg
103
+ f, constr = evaluate(calcfc, x, m_nlcon, amat, bvec)
104
+ cstrv = np.max(np.append(0, constr))
105
+
106
+ # Print a message about the function/constraint evaluation according to IPRINT.
107
+ fmsg(solver, "Initialization", iprint, k, rhobeg, f, x, cstrv, constr)
108
+
109
+ # Save X, F, CONSTR, CSTRV into the history.
110
+ savehist(maxhist, x, xhist, f, fhist, cstrv, chist, constr, conhist)
111
+
112
+ # Save F, CONSTR, and CSTRV to FVAL, CONMAT, and CVAL respectively.
113
+ evaluated[j] = True
114
+ fval[j] = f
115
+ conmat[:, j] = constr
116
+ cval[j] = cstrv
117
+
118
+ # Check whether to exit.
119
+ subinfo = checkbreak_con(maxfun, k, cstrv, ctol, f, ftarget, x)
120
+ if subinfo != INFO_DEFAULT:
121
+ info = subinfo
122
+ break
123
+
124
+ # Exchange the new vertex of the initial simplex with the optimal vertex if necessary.
125
+ # This is the ONLY part that is essentially non-parallel.
126
+ if j < num_vars and fval[j] < fval[num_vars]:
127
+ fval[j], fval[num_vars] = fval[num_vars], fval[j]
128
+ cval[j], cval[num_vars] = cval[num_vars], cval[j]
129
+ conmat[:, [j, num_vars]] = conmat[:, [num_vars, j]]
130
+ sim[:, num_vars] = x
131
+ sim[j, : j + 1] = -rhobeg # SIM[:, :j+1] is lower triangular
132
+
133
+ nf = np.count_nonzero(evaluated)
134
+
135
+ if evaluated.all():
136
+ # Initialize SIMI to the inverse of SIM[:, :num_vars]
137
+ simi = inv(sim[:, :num_vars])
138
+
139
+ # ==================#
140
+ # Calculation ends #
141
+ # ==================#
142
+
143
+ # Postconditions
144
+ if DEBUGGING:
145
+ assert nf <= maxfun, f"NF <= MAXFUN {srname}"
146
+ assert (
147
+ evaluated.size == num_vars + 1
148
+ ), f"EVALUATED.size == Num_vars + 1 {srname}"
149
+ # assert chist.size == maxchist, f'CHIST.size == MAXCHIST {srname}'
150
+ # assert conhist.shape== (num_constraints, maxconhist), f'CONHIST.shape == [M, MAXCONHIST] {srname}'
151
+ assert conmat.shape == (
152
+ num_constraints,
153
+ num_vars + 1,
154
+ ), f"CONMAT.shape = [M, N+1] {srname}"
155
+ assert not (
156
+ np.isnan(conmat).any() or np.isneginf(conmat).any()
157
+ ), f"CONMAT does not contain NaN/-Inf {srname}"
158
+ assert cval.size == num_vars + 1 and not (
159
+ any(cval < 0) or any(np.isnan(cval)) or any(np.isposinf(cval))
160
+ ), f"CVAL.shape == Num_vars+1 and CVAL does not contain negative values or NaN/+Inf {srname}"
161
+ # assert fhist.shape == maxfhist, f'FHIST.shape == MAXFHIST {srname}'
162
+ # assert maxfhist * (maxfhist - maxhist) == 0, f'FHIST.shape == 0 or MAXHIST {srname}'
163
+ assert fval.size == num_vars + 1 and not (
164
+ any(np.isnan(fval)) or any(np.isposinf(fval))
165
+ ), f"FVAL.shape == Num_vars+1 and FVAL is not NaN/+Inf {srname}"
166
+ # assert xhist.shape == (num_vars, maxxhist), f'XHIST.shape == [N, MAXXHIST] {srname}'
167
+ assert sim.shape == (num_vars, num_vars + 1), f"SIM.shape == [N, N+1] {srname}"
168
+ assert np.isfinite(sim).all(), f"SIM is finite {srname}"
169
+ assert all(
170
+ np.max(abs(sim[:, :num_vars]), axis=0) > 0
171
+ ), f"SIM(:, 1:N) has no zero column {srname}"
172
+ assert simi.shape == (num_vars, num_vars), f"SIMI.shape == [N, N] {srname}"
173
+ assert np.isfinite(simi).all(), f"SIMI is finite {srname}"
174
+ assert np.allclose(
175
+ sim[:, :num_vars] @ simi, np.eye(num_vars), rtol=0.1, atol=0.1
176
+ ) or not all(evaluated), f"SIMI = SIM(:, 1:N)^{-1} {srname}"
177
+
178
+ return evaluated, conmat, cval, sim, simi, fval, nf, info
179
+
180
+
181
+ def initfilt(
182
+ conmat, ctol, cweight, cval, fval, sim, evaluated, cfilt, confilt, ffilt, xfilt
183
+ ):
184
+ """
185
+ This function initializes the filter (XFILT, etc) that will be used when selecting
186
+ x at the end of the solver.
187
+ N.B.:
188
+ 1. Why not initialize the filters using XHIST, etc? Because the history is empty if
189
+ the user chooses not to output it.
190
+ 2. We decouple INITXFC and INITFILT so that it is easier to parallelize the former
191
+ if needed.
192
+ """
193
+
194
+ # Sizes
195
+ num_constraints = conmat.shape[0]
196
+ num_vars = sim.shape[0]
197
+ maxfilt = len(ffilt)
198
+
199
+ # Preconditions
200
+ if DEBUGGING:
201
+ assert num_constraints >= 0
202
+ assert num_vars >= 1
203
+ assert maxfilt >= 1
204
+ assert np.size(confilt, 0) == num_constraints and np.size(confilt, 1) == maxfilt
205
+ assert np.size(cfilt) == maxfilt
206
+ assert np.size(xfilt, 0) == num_vars and np.size(xfilt, 1) == maxfilt
207
+ assert np.size(ffilt) == maxfilt
208
+ assert (
209
+ np.size(conmat, 0) == num_constraints and np.size(conmat, 1) == num_vars + 1
210
+ )
211
+ assert not (np.isnan(conmat) | np.isneginf(conmat)).any()
212
+ assert np.size(cval) == num_vars + 1 and not any(
213
+ cval < 0 | np.isnan(cval) | np.isposinf(cval)
214
+ )
215
+ assert np.size(fval) == num_vars + 1 and not any(
216
+ np.isnan(fval) | np.isposinf(fval)
217
+ )
218
+ assert np.size(sim, 0) == num_vars and np.size(sim, 1) == num_vars + 1
219
+ assert np.isfinite(sim).all()
220
+ assert all(np.max(abs(sim[:, :num_vars]), axis=0) > 0)
221
+ assert np.size(evaluated) == num_vars + 1
222
+
223
+ # ====================#
224
+ # Calculation starts #
225
+ # ====================#
226
+
227
+ nfilt = 0
228
+ for i in range(num_vars + 1):
229
+ if evaluated[i]:
230
+ if i < num_vars:
231
+ x = sim[:, i] + sim[:, num_vars]
232
+ else:
233
+ x = sim[:, i] # i == num_vars, i.e. the last column
234
+ nfilt, cfilt, ffilt, xfilt, confilt = savefilt(
235
+ cval[i],
236
+ ctol,
237
+ cweight,
238
+ fval[i],
239
+ x,
240
+ nfilt,
241
+ cfilt,
242
+ ffilt,
243
+ xfilt,
244
+ conmat[:, i],
245
+ confilt,
246
+ )
247
+
248
+ # ==================#
249
+ # Calculation ends #
250
+ # ==================#
251
+
252
+ # Postconditions
253
+ if DEBUGGING:
254
+ assert nfilt <= maxfilt
255
+ assert np.size(confilt, 0) == num_constraints and np.size(confilt, 1) == maxfilt
256
+ assert not (
257
+ np.isnan(confilt[:, :nfilt]) | np.isneginf(confilt[:, :nfilt])
258
+ ).any()
259
+ assert np.size(cfilt) == maxfilt
260
+ assert not any(
261
+ cfilt[:nfilt] < 0 | np.isnan(cfilt[:nfilt]) | np.isposinf(cfilt[:nfilt])
262
+ )
263
+ assert np.size(xfilt, 0) == num_vars and np.size(xfilt, 1) == maxfilt
264
+ assert not (np.isnan(xfilt[:, :nfilt])).any()
265
+ # The last calculated X can be Inf (finite + finite can be Inf numerically).
266
+ assert np.size(ffilt) == maxfilt
267
+ assert not any(np.isnan(ffilt[:nfilt]) | np.isposinf(ffilt[:nfilt]))
268
+
269
+ return nfilt