eqc-models 0.11.0__py3-none-any.whl → 0.12.0__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 (71) hide show
  1. eqc_models-0.12.0.data/platlib/eqc_models/assignment/__init__.py +6 -0
  2. eqc_models-0.12.0.data/platlib/eqc_models/assignment/resource.py +165 -0
  3. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/polyeval.c +4208 -3435
  4. eqc_models-0.12.0.data/platlib/eqc_models/base/polyeval.cpython-310-darwin.so +0 -0
  5. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/quadratic.py +2 -2
  6. eqc_models-0.12.0.data/platlib/eqc_models/base/results.py +166 -0
  7. eqc_models-0.12.0.data/platlib/eqc_models/graph/__init__.py +9 -0
  8. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/graph/base.py +8 -4
  9. eqc_models-0.12.0.data/platlib/eqc_models/graph/shortestpath.py +157 -0
  10. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/classifierbase.py +31 -5
  11. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/classifierqboost.py +14 -1
  12. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/classifierqsvm.py +223 -19
  13. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/clustering.py +5 -5
  14. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/clusteringbase.py +1 -1
  15. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/decomposition.py +39 -16
  16. eqc_models-0.12.0.data/platlib/eqc_models/process/base.py +18 -0
  17. eqc_models-0.12.0.data/platlib/eqc_models/process/mpc.py +17 -0
  18. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/solvers/__init__.py +1 -5
  19. eqc_models-0.12.0.data/platlib/eqc_models/solvers/eqcdirect.py +71 -0
  20. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/solvers/qciclient.py +6 -3
  21. {eqc_models-0.11.0.dist-info → eqc_models-0.12.0.dist-info}/METADATA +2 -3
  22. eqc_models-0.12.0.dist-info/RECORD +65 -0
  23. {eqc_models-0.11.0.dist-info → eqc_models-0.12.0.dist-info}/WHEEL +1 -1
  24. eqc_models-0.11.0.data/platlib/eqc_models/assignment/__init__.py +0 -5
  25. eqc_models-0.11.0.data/platlib/eqc_models/base/polyeval.cpython-310-darwin.so +0 -0
  26. eqc_models-0.11.0.data/platlib/eqc_models/base/results.py +0 -94
  27. eqc_models-0.11.0.data/platlib/eqc_models/graph/__init__.py +0 -6
  28. eqc_models-0.11.0.data/platlib/eqc_models/sequence/scheduling.py +0 -29
  29. eqc_models-0.11.0.dist-info/RECORD +0 -61
  30. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/compile_extensions.py +0 -0
  31. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/__init__.py +0 -0
  32. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/algorithms/__init__.py +0 -0
  33. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/algorithms/base.py +0 -0
  34. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/algorithms/penaltymultiplier.py +0 -0
  35. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/allocation/__init__.py +0 -0
  36. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/allocation/allocation.py +0 -0
  37. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/allocation/portbase.py +0 -0
  38. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/allocation/portmomentum.py +0 -0
  39. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/assignment/qap.py +0 -0
  40. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/assignment/setpartition.py +0 -0
  41. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/__init__.py +0 -0
  42. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/base.py +0 -0
  43. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/constraints.py +0 -0
  44. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/operators.py +0 -0
  45. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/polyeval.pyx +0 -0
  46. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/polynomial.py +0 -0
  47. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/combinatorics/__init__.py +0 -0
  48. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/combinatorics/setcover.py +0 -0
  49. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/combinatorics/setpartition.py +0 -0
  50. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/decoding.py +0 -0
  51. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/graph/hypergraph.py +0 -0
  52. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/graph/maxcut.py +0 -0
  53. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/graph/maxkcut.py +0 -0
  54. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/graph/partition.py +0 -0
  55. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/__init__.py +0 -0
  56. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/cvqboost_hamiltonian.pyx +0 -0
  57. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.c +0 -0
  58. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.h +0 -0
  59. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/forecast.py +0 -0
  60. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/forecastbase.py +0 -0
  61. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/regressor.py +0 -0
  62. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/regressorbase.py +0 -0
  63. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/reservoir.py +0 -0
  64. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/sequence/__init__.py +0 -0
  65. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/sequence/tsp.py +0 -0
  66. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/utilities/__init__.py +0 -0
  67. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/utilities/fileio.py +0 -0
  68. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/utilities/polynomial.py +0 -0
  69. {eqc_models-0.11.0.data → eqc_models-0.12.0.data}/platlib/eqc_models/utilities/qplib.py +0 -0
  70. {eqc_models-0.11.0.dist-info → eqc_models-0.12.0.dist-info}/licenses/LICENSE.txt +0 -0
  71. {eqc_models-0.11.0.dist-info → eqc_models-0.12.0.dist-info}/top_level.txt +0 -0
@@ -8,28 +8,224 @@ import json
8
8
  import warnings
9
9
  from functools import wraps
10
10
  import numpy as np
11
+ from sklearn.preprocessing import MinMaxScaler
11
12
 
12
13
  from eqc_models.ml.classifierbase import ClassifierBase
13
14
 
14
15
 
15
16
  class QSVMClassifier(ClassifierBase):
16
17
  """An implementation of QSVM classifier that uses QCi's Dirac-3.
17
-
18
+
18
19
  Parameters
19
20
  ----------
20
-
21
+
21
22
  relaxation_schedule: Relaxation schedule used by Dirac-3; default:
22
23
  2.
24
+
25
+ num_samples: Number of samples used by Dirac-3; default: 1.
26
+
27
+ solver_access: Solver access type: cloud or direct; default: cloud.
28
+
29
+ ip_addr: IP address of the device when direct access is used; default: None.
30
+
31
+ port: Port number of the device when direct access is used; default: None.
23
32
 
33
+ lambda_coef: The penalty multipler
34
+
35
+ Examples
36
+ -----------
37
+
38
+ >>> from sklearn import datasets
39
+ >>> from sklearn.preprocessing import MinMaxScaler
40
+ >>> from sklearn.model_selection import train_test_split
41
+ >>> iris = datasets.load_iris()
42
+ >>> X = iris.data
43
+ >>> y = iris.target
44
+ >>> scaler = MinMaxScaler()
45
+ >>> X = scaler.fit_transform(X)
46
+ >>> for i in range(len(y)):
47
+ ... if y[i] == 0:
48
+ ... y[i] = -1
49
+ ... elif y[i] == 2:
50
+ ... y[i] = 1
51
+ >>> X_train, X_test, y_train, y_test = train_test_split(
52
+ ... X,
53
+ ... y,
54
+ ... test_size=0.2,
55
+ ... random_state=42,
56
+ ... )
57
+ >>> from eqc_models.ml.classifierqsvm import QSVMClassifier
58
+ >>> obj = QSVMClassifier(
59
+ ... relaxation_schedule=2,
60
+ ... num_samples=1,
61
+ ... )
62
+ >>> from contextlib import redirect_stdout
63
+ >>> import io
64
+ >>> f = io.StringIO()
65
+ >>> with redirect_stdout(f):
66
+ ... obj = obj.fit(X_train, y_train)
67
+ ... y_train_prd = obj.predict(X_train)
68
+ ... y_test_prd = obj.predict(X_test)
69
+
70
+ """
71
+
72
+ def __init__(
73
+ self,
74
+ relaxation_schedule=1,
75
+ num_samples=1,
76
+ solver_access="cloud",
77
+ ip_addr=None,
78
+ port=None,
79
+ lambda_coef=1.0,
80
+ ):
81
+ super(QSVMClassifier).__init__()
82
+
83
+ assert solver_access in ["cloud", "direct"]
84
+
85
+ self.relaxation_schedule = relaxation_schedule
86
+ self.num_samples = num_samples
87
+ self.solver_access = solver_access
88
+ self.ip_addr = ip_addr
89
+ self.port = port
90
+ self.lambda_coef = lambda_coef
91
+ self.fea_scaler = MinMaxScaler(feature_range=(-1, 1))
92
+
93
+ def fit(self, X, y):
94
+ """
95
+ Build a QSVM classifier from the training set (X, y).
96
+
97
+ Parameters
98
+ ----------
99
+ X : {array-like, sparse matrix} of shape (n_samples, n_features)
100
+ The training input samples.
101
+
102
+ y : array-like of shape (n_samples,)
103
+ The target values.
104
+
105
+ Returns
106
+ -------
107
+ Response of Dirac-3 in JSON format.
108
+ """
109
+
110
+ assert X.shape[0] == y.shape[0], "Inconsistent sizes!"
111
+
112
+ assert set(y) == {-1, 1}, "Target values should be in {-1, 1}"
113
+
114
+ X = self.fea_scaler.fit_transform(X)
115
+
116
+ J, C, sum_constraint = self.get_hamiltonian(X, y)
117
+
118
+ assert J.shape[0] == J.shape[1], "Inconsistent hamiltonian size!"
119
+ assert J.shape[0] == C.shape[0], "Inconsistent hamiltonian size!"
120
+
121
+ self.set_model(J, C, sum_constraint)
122
+
123
+ sol, response = self.solve()
124
+
125
+ assert len(sol) == C.shape[0], "Inconsistent solution size!"
126
+
127
+ self.params = self.convert_sol_to_params(sol)
128
+
129
+ self.X_train = X
130
+ self.y_train = y
131
+
132
+ return response
133
+
134
+ def predict_raw(self, X: np.array):
135
+ """
136
+ Predict classes for X.
137
+
138
+ Parameters
139
+ ----------
140
+ X : {array-like, sparse matrix} of shape (n_samples, n_features)
141
+
142
+ Returns
143
+ -------
144
+ y : ndarray of shape (n_samples,)
145
+ The predicted classes.
146
+ """
147
+ n_records = X.shape[0]
148
+ X = self.fea_scaler.transform(X)
149
+ X_tilde = np.concatenate((X, np.ones((n_records, 1))), axis=1)
150
+
151
+ y = np.einsum("i,ki->k", self.params, X_tilde)
152
+
153
+ return y
154
+
155
+ def predict(self, X: np.array):
156
+ """
157
+ Predict classes for X.
158
+
159
+ Parameters
160
+ ----------
161
+ X : {array-like, sparse matrix} of shape (n_samples, n_features)
162
+
163
+ Returns
164
+ -------
165
+ y : ndarray of shape (n_samples,)
166
+ The predicted classes.
167
+ """
168
+
169
+ y = self.predict_raw(X)
170
+ y = np.sign(y)
171
+
172
+ return y
173
+
174
+ def get_hamiltonian(
175
+ self,
176
+ X: np.array,
177
+ y: np.array,
178
+ ):
179
+ n_records = X.shape[0]
180
+ n_dims = X.shape[1]
181
+
182
+ J = np.zeros(shape=(1 + n_dims, 1 + n_dims), dtype=np.float32)
183
+ C = np.zeros(shape=(1 + n_dims,), dtype=np.float32)
184
+
185
+ X_tilde = np.concatenate((X, np.ones((n_records, 1))), axis=1)
186
+
187
+ J = self.lambda_coef * np.einsum(
188
+ "i,ik,il->kl", y**2, X_tilde, X_tilde
189
+ )
190
+
191
+ for k in range(n_dims):
192
+ J[k][k] += 0.5
193
+
194
+ C = -2.0 * self.lambda_coef * np.einsum("i,ik->k", y, X_tilde)
195
+
196
+ J = 0.5 * (J + J.transpose())
197
+ C = C.reshape((1 + n_dims, 1))
198
+
199
+ return J, C, 1.0
200
+
201
+ def convert_sol_to_params(self, sol):
202
+ return np.array(sol)
203
+
204
+
205
+ class QSVMClassifierDual(ClassifierBase):
206
+ """An implementation of dual QSVM classifier that uses QCi's Dirac-3.
207
+
208
+ Parameters
209
+ ----------
210
+
211
+ relaxation_schedule: Relaxation schedule used by Dirac-3; default:
212
+ 2.
213
+
24
214
  num_samples: Number of samples used by Dirac-3; default: 1.
215
+
216
+ solver_access: Solver access type: cloud or direct; default: cloud.
217
+
218
+ ip_addr: IP address of the device when direct access is used; default: None.
219
+
220
+ port: Port number of the device when direct access is used; default: None.
25
221
 
26
222
  upper_limit: Coefficient upper limit; a regularization parameter;
27
223
  default: 1.0.
28
-
224
+
29
225
  gamma: Gaussian kernel parameter; default: 1.0.
30
-
226
+
31
227
  eta: A penalty multiplier; default: 1.0.
32
-
228
+
33
229
  zeta: A penalty multiplier; default: 1.0.
34
230
 
35
231
  Examples
@@ -54,8 +250,8 @@ class QSVMClassifier(ClassifierBase):
54
250
  ... test_size=0.2,
55
251
  ... random_state=42,
56
252
  ... )
57
- >>> from eqc_models.ml.classifierqsvm import QSVMClassifier
58
- >>> obj = QSVMClassifier(
253
+ >>> from eqc_models.ml.classifierqsvm import QSVMClassifierDual
254
+ >>> obj = QSVMClassifierDual(
59
255
  ... relaxation_schedule=2,
60
256
  ... num_samples=1,
61
257
  ... upper_limit=1.0,
@@ -70,22 +266,30 @@ class QSVMClassifier(ClassifierBase):
70
266
  ... obj = obj.fit(X_train, y_train)
71
267
  ... y_train_prd = obj.predict(X_train)
72
268
  ... y_test_prd = obj.predict(X_test)
73
-
269
+
74
270
  """
75
-
271
+
76
272
  def __init__(
77
273
  self,
78
274
  relaxation_schedule=2,
79
275
  num_samples=1,
276
+ solver_access="cloud",
277
+ ip_addr=None,
278
+ port=None,
80
279
  upper_limit=1.0,
81
280
  gamma=1.0,
82
281
  eta=1.0,
83
282
  zeta=1.0,
84
- ):
85
- super(QSVMClassifier).__init__()
283
+ ):
284
+ super(QSVMClassifierDual).__init__()
86
285
 
286
+ assert solver_access in ["cloud", "direct"]
287
+
87
288
  self.relaxation_schedule = relaxation_schedule
88
289
  self.num_samples = num_samples
290
+ self.solver_access = solver_access
291
+ self.ip_addr = ip_addr
292
+ self.port = port
89
293
  self.upper_limit = upper_limit
90
294
  self.gamma = gamma
91
295
  self.eta = eta
@@ -97,20 +301,20 @@ class QSVMClassifier(ClassifierBase):
97
301
  def fit(self, X, y):
98
302
  """
99
303
  Build a QSVM classifier from the training set (X, y).
100
-
304
+
101
305
  Parameters
102
306
  ----------
103
307
  X : {array-like, sparse matrix} of shape (n_samples, n_features)
104
- The training input samples.
105
-
308
+ The training input samples.
309
+
106
310
  y : array-like of shape (n_samples,)
107
311
  The target values.
108
-
312
+
109
313
  Returns
110
314
  -------
111
315
  Response of Dirac-3 in JSON format.
112
316
  """
113
-
317
+
114
318
  assert X.shape[0] == y.shape[0], "Inconsistent sizes!"
115
319
 
116
320
  assert set(y) == {-1, 1}, "Target values should be in {-1, 1}"
@@ -144,17 +348,17 @@ class QSVMClassifier(ClassifierBase):
144
348
  def predict(self, X: np.array):
145
349
  """
146
350
  Predict classes for X.
147
-
351
+
148
352
  Parameters
149
353
  ----------
150
354
  X : {array-like, sparse matrix} of shape (n_samples, n_features)
151
-
355
+
152
356
  Returns
153
357
  -------
154
358
  y : ndarray of shape (n_samples,)
155
359
  The predicted classes.
156
360
  """
157
-
361
+
158
362
  assert self.X_train is not None, "Model not trained yet!"
159
363
  assert self.y_train is not None, "Model not trained yet!"
160
364
 
@@ -140,14 +140,14 @@ class GraphClustering(ClusteringBase):
140
140
 
141
141
  self.set_model(J, C, sum_constraint)
142
142
 
143
- sol = self.solve()
144
-
143
+ sol, response = self.solve()
144
+
145
145
  assert len(sol) == C.shape[0], "Inconsistent solution size!"
146
146
  assert len(sol) == self.num_clusters * self.num_nodes
147
147
 
148
148
  self.labels = self.get_labels(sol)
149
149
 
150
- return self
150
+ return response
151
151
 
152
152
  def fit_predict(self):
153
153
  """
@@ -300,14 +300,14 @@ class Clustering(ClusteringBase):
300
300
 
301
301
  self.set_model(J, C, sum_constraint)
302
302
 
303
- sol = self.solve()
303
+ sol, response = self.solve()
304
304
 
305
305
  assert len(sol) == C.shape[0], "Inconsistent solution size!"
306
306
  assert len(sol) == self.num_clusters * num_items
307
307
 
308
308
  self.labels = self.get_labels(sol, num_items)
309
309
 
310
- return self
310
+ return response
311
311
 
312
312
  def fit_predict(self, X: np.array):
313
313
  """
@@ -78,7 +78,7 @@ class ClusteringBase(QuadraticModel):
78
78
 
79
79
  print(response)
80
80
 
81
- return sol
81
+ return sol, response
82
82
 
83
83
  def get_labels(self, sol):
84
84
  pass
@@ -21,17 +21,17 @@ from eqc_models.solvers.qciclient import (
21
21
 
22
22
  class DecompBase(QuadraticModel):
23
23
  """An Base class for decomposition algorithms.
24
-
24
+
25
25
  Parameters
26
26
  ----------
27
-
27
+
28
28
  relaxation_schedule: Relaxation schedule used by Dirac-3; default:
29
29
  2.
30
-
30
+
31
31
  num_samples: Number of samples used by Dirac-3; default: 1.
32
32
 
33
33
  """
34
-
34
+
35
35
  def __init__(
36
36
  self,
37
37
  relaxation_schedule=2,
@@ -163,8 +163,7 @@ class DecompBase(QuadraticModel):
163
163
 
164
164
 
165
165
  class PCA(DecompBase):
166
- """
167
- An implementation of Principal component analysis (PCA) that
166
+ """An implementation of Principal component analysis (PCA) that
168
167
  uses QCi's Dirac-3.
169
168
 
170
169
  Linear dimensionality reduction using Singular Value
@@ -173,18 +172,22 @@ class PCA(DecompBase):
173
172
 
174
173
  Parameters
175
174
  ----------
176
-
175
+
177
176
  n_components: Number of components to keep; if n_components is not
178
177
  set all components are kept; default: None.
179
-
178
+
180
179
  relaxation_schedule: Relaxation schedule used by Dirac-3; default:
181
180
  2.
182
-
181
+
183
182
  num_samples: Number of samples used by Dirac-3; default: 1.
184
183
 
184
+ mode: Compute the largest or smallest principal components,
185
+ largest_components vs. smallest_components; default:
186
+ largest_components.
187
+
185
188
  Examples
186
189
  -----------
187
-
190
+
188
191
  >>> from sklearn import datasets
189
192
  >>> iris = datasets.load_iris()
190
193
  >>> X = iris.data
@@ -202,18 +205,25 @@ class PCA(DecompBase):
202
205
  ... num_samples=1,
203
206
  ... )
204
207
  ... X_pca = obj.fit_transform(X)
205
-
208
+
206
209
  """
207
-
210
+
208
211
  def __init__(
209
212
  self,
210
213
  n_components=None,
211
214
  relaxation_schedule=2,
212
215
  num_samples=1,
216
+ mode="largest_components",
213
217
  ):
214
218
  self.n_components = n_components
215
219
  self.relaxation_schedule = relaxation_schedule
216
220
  self.num_samples = num_samples
221
+
222
+ assert mode in ["largest_components", "smallest_components"], (
223
+ "Invalid value of mode <%s>" % mode
224
+ )
225
+
226
+ self.mode = mode
217
227
  self.X = None
218
228
  self.X_pca = None
219
229
 
@@ -224,12 +234,20 @@ class PCA(DecompBase):
224
234
  num_records = X.shape[0]
225
235
  num_features = X.shape[1]
226
236
 
227
- J = -np.matmul(X.transpose(), X)
237
+ J = np.matmul(X.transpose(), X)
228
238
 
229
239
  assert J.shape[0] == num_features
230
240
  assert J.shape[1] == num_features
231
241
 
232
- C = np.zeros((num_features, 1))
242
+ C = -np.sum(J, axis=1)
243
+
244
+ assert C.shape[0] == num_features
245
+
246
+ C = C.reshape((num_features, 1))
247
+
248
+ if self.mode == "largest_components":
249
+ J = -J
250
+ C = -C
233
251
 
234
252
  return J, C
235
253
 
@@ -239,12 +257,17 @@ class PCA(DecompBase):
239
257
  assert J.shape[0] == J.shape[1], "Inconsistent hamiltonian size!"
240
258
  assert J.shape[0] == C.shape[0], "Inconsistent hamiltonian size!"
241
259
 
260
+ sum_constraint = 0.5 * (1.0 + C.shape[0])
261
+
242
262
  self._set_model(J, C, 1.0)
243
263
 
244
264
  sol, response = self._solve()
245
265
 
246
266
  assert len(sol) == C.shape[0], "Inconsistent solution size!"
247
267
 
268
+ sol = np.array(sol)
269
+ sol = 2.0 * sol - 1.0
270
+
248
271
  fct = np.linalg.norm(sol)
249
272
  if fct > 0:
250
273
  fct = 1.0 / fct
@@ -282,7 +305,7 @@ class PCA(DecompBase):
282
305
 
283
306
  Returns
284
307
  -------
285
- responses.
308
+ responses.
286
309
  A dirct containing Dirac responses.
287
310
  """
288
311
 
@@ -310,7 +333,7 @@ class PCA(DecompBase):
310
333
  assert X.shape == self.X.shape, "Inconsistent size!"
311
334
 
312
335
  resp_hash["component_%d_response" % (i + 1)] = resp
313
-
336
+
314
337
  self.X_pca = np.array(self.X_pca).transpose()
315
338
 
316
339
  assert self.X_pca.shape[0] == self.X.shape[0]
@@ -0,0 +1,18 @@
1
+ import networkx as nx
2
+ from eqc_models.base import ConstrainedPolynomialModel
3
+
4
+ class ProcessModel:
5
+ """
6
+ Given a directed graph $G$ that describes a process flow, optimize the
7
+ flow.
8
+
9
+ """
10
+ def __init__(self, G : nx.DiGraph):
11
+ self.G = G
12
+
13
+ @staticmethod
14
+ def process_constraints(G : nx.DiGraph):
15
+ """ Build process constraints from the graph """
16
+
17
+ def constraints(self) -> Tuple[np.ndarray]:
18
+ pass
@@ -0,0 +1,17 @@
1
+ from eqc_models.process.base import ProcessModel
2
+
3
+ class ModelPredictiveControl(ProcessModel):
4
+ """ Base class for implementing MPC optimization problems """
5
+
6
+ def __init__(self, G : nx.Graph, V : int=1, V_T:float=0.0):
7
+ self.processArgs(*args, **kwargs)
8
+ self.T = T
9
+ self.V_T = V_T
10
+ super(ModelPredictiveControl, self).__init__(G)
11
+
12
+ def processArgs(self, *args, **kwargs):
13
+ """ Provide a method to capture arguments necessary for configuring an instance """
14
+ raise NotImplementedError("subclass must implement processArgs")
15
+
16
+ def constraints(self) -> Tuple[np.ndarray]:
17
+ pass
@@ -1,9 +1,5 @@
1
1
  # (C) Quantum Computing Inc., 2024.
2
- try:
3
- from .eqcdirect import Dirac3DirectSolver, EqcDirectSolver
4
- except ImportError:
5
- # eqc-direct is not available
6
- Dirac3DirectSolver = None
2
+ from .eqcdirect import Dirac3DirectSolver
7
3
  from .qciclient import (Dirac1CloudSolver, Dirac3CloudSolver, QciClientSolver,
8
4
  Dirac3IntegerCloudSolver, Dirac3ContinuousCloudSolver)
9
5
 
@@ -0,0 +1,71 @@
1
+ # (C) Quantum Computing Inc., 2025.
2
+ import logging
3
+ import numpy as np
4
+ from eqc_direct.client import EqcClient
5
+ from eqc_models.base.base import ModelSolver
6
+ from eqc_models.base.results import SolutionResults
7
+
8
+ log = logging.getLogger(name=__name__)
9
+
10
+
11
+ class Dirac3DirectSolver(ModelSolver):
12
+ ip_addr: str = "localhost"
13
+ port: str = "50051"
14
+ cert_file: str = None
15
+
16
+ def solve(
17
+ self,
18
+ model,
19
+ sum_constraint,
20
+ relaxation_schedule=1,
21
+ num_samples=1,
22
+ solution_precision=None,
23
+ mean_photon_number=None,
24
+ quantum_fluctuation_coefficient=None,
25
+ ):
26
+ polynomial = model.polynomial
27
+ coefficients = polynomial.coefficients
28
+ indices = polynomial.indices
29
+ num_variables = 0
30
+ for i in range(len(indices)):
31
+ if max(indices[i]) > num_variables:
32
+ num_variables = max(indices[i])
33
+
34
+ print("Num variables:", num_variables)
35
+
36
+ client = self.client
37
+ lock_id, startts, endts = client.wait_for_lock()
38
+
39
+ # assert lock["status_code"] == 0
40
+
41
+ # lock_id = lock["lock_id"]
42
+ response = None
43
+ try:
44
+ response = client.solve_sum_constrained(
45
+ coefficients,
46
+ indices,
47
+ num_variables,
48
+ num_samples=num_samples,
49
+ lock_id=lock_id,
50
+ relaxation_schedule=relaxation_schedule,
51
+ sum_constraint=sum_constraint,
52
+ solution_precision=solution_precision,
53
+ mean_photon_number=mean_photon_number,
54
+ quantum_fluctuation_coefficient=quantum_fluctuation_coefficient,
55
+ )
56
+ finally:
57
+ client.release_lock(lock_id=lock_id)
58
+
59
+ return response
60
+
61
+ def connect(self, ip_addr: str, port: str, cert_file: str = None):
62
+ self.ip_addr = ip_addr
63
+ self.port = port
64
+ self.cert_file = cert_file
65
+ client = self.client
66
+
67
+ return client.system_status()
68
+
69
+ @property
70
+ def client(self) -> EqcClient:
71
+ return EqcClient(self.ip_addr, self.port, cert_file=self.cert_file)
@@ -519,7 +519,8 @@ class Dirac3CloudSolver(Dirac3Mixin, QciClientSolver):
519
519
  of photons that are present in a given quantum state.
520
520
  Modify this value to control the relaxation schedule more
521
521
  precisely than the four presets given in schedules 1
522
- through 4. Allowed values are decimals between 0.1 and 2.
522
+ through 4. Allowed values are decimals between 0.000133333333333 and
523
+ 0.001.
523
524
  quantum_fluctuation_coefficient: int
524
525
  an integer value which Sets the amount of loss introduced
525
526
  into the system for each loop during the measurement process.
@@ -622,7 +623,8 @@ class Dirac3IntegerCloudSolver(Dirac3Mixin, QciClientSolver):
622
623
  of photons that are present in a given quantum state.
623
624
  Modify this value to control the relaxation schedule more
624
625
  precisely than the four presets given in schedules 1
625
- through 4. Allowed values are decimals between 0.1 and 2.
626
+ through 4. Allowed values are decimals between 0.000133333333333
627
+ and 0.001.
626
628
  quantum_fluctuation_coefficient: int
627
629
  an integer value which Sets the amount of loss introduced
628
630
  into the system for each loop during the measurement process.
@@ -716,7 +718,8 @@ class Dirac3ContinuousCloudSolver(Dirac3Mixin, QciClientSolver):
716
718
  of photons that are present in a given quantum state.
717
719
  Modify this value to control the relaxation schedule more
718
720
  precisely than the four presets given in schedules 1
719
- through 4. Allowed values are decimals between 0.1 and 2.
721
+ through 4. Allowed values are decimals between 0.000133333333333
722
+ and 0.001.
720
723
  quantum_fluctuation_coefficient: int
721
724
  an integer value which Sets the amount of loss introduced
722
725
  into the system for each loop during the measurement process.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eqc-models
3
- Version: 0.11.0
3
+ Version: 0.12.0
4
4
  Summary: Optimization and ML modeling package targeting EQC devices
5
5
  Author: Quantum Computing Inc.
6
6
  Author-email: support@quantumcomputinginc.com
@@ -16,8 +16,7 @@ Requires-Dist: pandas>=2.1.0
16
16
  Requires-Dist: scikit-learn>=1.2.1
17
17
  Requires-Dist: qci-client<5,>=4.3.0
18
18
  Requires-Dist: emucore-direct==1.0.6
19
- Provides-Extra: direct
20
- Requires-Dist: eqc-direct<2,>=1.3.0; extra == "direct"
19
+ Requires-Dist: eqc-direct<3,>=2.0.1
21
20
  Provides-Extra: dev
22
21
  Requires-Dist: pytest<8,>=7.1.0; extra == "dev"
23
22
  Requires-Dist: pytest-cov; extra == "dev"