eqc-models 0.11.1__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 (68) hide show
  1. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/polyeval.c +4208 -3435
  2. eqc_models-0.12.0.data/platlib/eqc_models/base/polyeval.cpython-310-darwin.so +0 -0
  3. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/quadratic.py +2 -2
  4. eqc_models-0.12.0.data/platlib/eqc_models/graph/__init__.py +9 -0
  5. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/graph/base.py +8 -4
  6. eqc_models-0.12.0.data/platlib/eqc_models/graph/shortestpath.py +157 -0
  7. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/classifierbase.py +31 -5
  8. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/classifierqboost.py +14 -1
  9. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/classifierqsvm.py +28 -0
  10. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/clustering.py +5 -5
  11. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/clusteringbase.py +1 -1
  12. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/process/base.py +6 -1
  13. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/process/mpc.py +1 -1
  14. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/solvers/__init__.py +1 -5
  15. eqc_models-0.12.0.data/platlib/eqc_models/solvers/eqcdirect.py +71 -0
  16. {eqc_models-0.11.1.dist-info → eqc_models-0.12.0.dist-info}/METADATA +2 -3
  17. eqc_models-0.12.0.dist-info/RECORD +65 -0
  18. {eqc_models-0.11.1.dist-info → eqc_models-0.12.0.dist-info}/WHEEL +1 -1
  19. eqc_models-0.11.1.data/platlib/eqc_models/base/polyeval.cpython-310-darwin.so +0 -0
  20. eqc_models-0.11.1.data/platlib/eqc_models/graph/__init__.py +0 -6
  21. eqc_models-0.11.1.dist-info/RECORD +0 -63
  22. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/compile_extensions.py +0 -0
  23. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/__init__.py +0 -0
  24. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/algorithms/__init__.py +0 -0
  25. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/algorithms/base.py +0 -0
  26. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/algorithms/penaltymultiplier.py +0 -0
  27. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/allocation/__init__.py +0 -0
  28. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/allocation/allocation.py +0 -0
  29. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/allocation/portbase.py +0 -0
  30. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/allocation/portmomentum.py +0 -0
  31. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/assignment/__init__.py +0 -0
  32. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/assignment/qap.py +0 -0
  33. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/assignment/resource.py +0 -0
  34. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/assignment/setpartition.py +0 -0
  35. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/__init__.py +0 -0
  36. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/base.py +0 -0
  37. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/constraints.py +0 -0
  38. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/operators.py +0 -0
  39. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/polyeval.pyx +0 -0
  40. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/polynomial.py +0 -0
  41. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/base/results.py +0 -0
  42. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/combinatorics/__init__.py +0 -0
  43. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/combinatorics/setcover.py +0 -0
  44. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/combinatorics/setpartition.py +0 -0
  45. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/decoding.py +0 -0
  46. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/graph/hypergraph.py +0 -0
  47. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/graph/maxcut.py +0 -0
  48. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/graph/maxkcut.py +0 -0
  49. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/graph/partition.py +0 -0
  50. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/__init__.py +0 -0
  51. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/cvqboost_hamiltonian.pyx +0 -0
  52. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.c +0 -0
  53. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.h +0 -0
  54. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/decomposition.py +0 -0
  55. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/forecast.py +0 -0
  56. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/forecastbase.py +0 -0
  57. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/regressor.py +0 -0
  58. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/regressorbase.py +0 -0
  59. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/ml/reservoir.py +0 -0
  60. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/sequence/__init__.py +0 -0
  61. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/sequence/tsp.py +0 -0
  62. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/solvers/qciclient.py +0 -0
  63. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/utilities/__init__.py +0 -0
  64. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/utilities/fileio.py +0 -0
  65. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/utilities/polynomial.py +0 -0
  66. {eqc_models-0.11.1.data → eqc_models-0.12.0.data}/platlib/eqc_models/utilities/qplib.py +0 -0
  67. {eqc_models-0.11.1.dist-info → eqc_models-0.12.0.dist-info}/licenses/LICENSE.txt +0 -0
  68. {eqc_models-0.11.1.dist-info → eqc_models-0.12.0.dist-info}/top_level.txt +0 -0
@@ -245,6 +245,6 @@ class ConstrainedQuadraticModel(ConstraintsMixIn, QuadraticModel):
245
245
  return self.lhs, self.rhs
246
246
 
247
247
  def evaluateObjective(self, solution: np.ndarray) -> float:
248
- J = self.quad_objective
249
- C = self.linear_objective
248
+ J = np.array(self.quad_objective)
249
+ C = np.array(self.linear_objective)
250
250
  return np.squeeze(C.T @ solution + solution.T@J@solution)
@@ -0,0 +1,9 @@
1
+ # (C) Quantum Computing Inc., 2024.
2
+
3
+ from .base import EdgeMixin, EdgeModel, GraphModel, NodeModel
4
+ from .maxcut import MaxCutModel
5
+ from .partition import GraphPartitionModel
6
+
7
+ __all__ = ["MaxCutModel", "GraphPartitionModel",
8
+ "EdgeMixin", "EdgeModel", "GraphModel",
9
+ "NodeModel"]
@@ -7,7 +7,7 @@ class GraphModel(QuadraticModel):
7
7
  """ """
8
8
  def __init__(self, G : nx.Graph):
9
9
  self.G = G
10
- super().__init__(*self.costFunction())
10
+ super(GraphModel, self).__init__(*self.costFunction())
11
11
 
12
12
  @property
13
13
  def linear_objective(self):
@@ -63,12 +63,16 @@ class TwoPartitionModel(NodeModel):
63
63
 
64
64
  """
65
65
 
66
- class EdgeModel(GraphModel):
67
- """ Create a model where the variables are edge-based """
66
+ class EdgeMixin:
68
67
 
69
68
  @property
70
69
  def variables(self) -> List[str]:
71
70
  """ Provide a variable name to index lookup; order enforced by sorting the list before returning """
72
- names = [f"({u},{v})" for u, v in self.G.edges]
71
+ names = [(u, v) for u, v in self.G.edges]
73
72
  names.sort()
74
73
  return names
74
+
75
+ class EdgeModel(EdgeMixin, GraphModel):
76
+ """ Create a model where the variables are edge-based """
77
+
78
+
@@ -0,0 +1,157 @@
1
+ r"""
2
+ MIP Shortest Path implementation
3
+
4
+ Given a graph $G$ and nodes $s$ and $t$, find the shortest path
5
+ by edge weight between $s$ and $t$.
6
+
7
+ $$
8
+ \min sum_ij w_ij x_ij
9
+ $$
10
+ subject to
11
+ $$
12
+ \sum_{(u,v)\in E} x_{u,v} - \sum{(v,u)\in E} x_{v,u} = 0 \forall u\in N\\{s,t}
13
+ $$
14
+ and
15
+ $$
16
+ \sum_{(s,v)\in E} x_{s,v} = 1
17
+ $$
18
+ and
19
+ $$
20
+ \sum_{(u,t)\in E} x_{u,t} = 1
21
+ $$
22
+
23
+ """
24
+
25
+ from typing import Any, Dict, Tuple
26
+ import logging
27
+ import numpy as np
28
+ import networkx as nx
29
+ from eqc_models.graph import EdgeMixin
30
+ from eqc_models.base.quadratic import ConstrainedQuadraticModel
31
+
32
+ log = logging.getLogger(name=__name__)
33
+
34
+ class ShortestPathModel(EdgeMixin, ConstrainedQuadraticModel):
35
+ """
36
+ ShortestPathModel describes the MIP formulation for the
37
+ shortest path problem.
38
+
39
+ Parameters
40
+ -------------
41
+
42
+ G : nx.DiGraph
43
+ A directed graph which is assumed to be connected. A graph
44
+ with disconnected subgraphs may reveal a solution if $s$ and $t$
45
+ are in the same subgraph, but testing for the existence of a path
46
+ between s and t using this model is not recommended. This is
47
+ due to the difficulty posed by selecting a penalty multiplier
48
+ large enough to enforce the panalties, which DNE in the infeasible
49
+ case.
50
+ s : Any
51
+ This is the label for the start node.
52
+ t : Any
53
+ This is the label for the end node.
54
+
55
+
56
+ """
57
+
58
+ def __init__(self, G: nx.DiGraph, s : Any, t : Any):
59
+ self.G = G
60
+ self.s = s
61
+ self.t = t
62
+ self.lhs, self.rhs = self.buildConstraints()
63
+ C, J = self.buildObjective()
64
+ super(ShortestPathModel, self).__init__(C, J, self.lhs, self.rhs)
65
+
66
+ def buildConstraints(self) -> Tuple[np.ndarray,np.ndarray]:
67
+ """
68
+ Constraints:
69
+ $$
70
+ sum_j x[i,l] - sum_j x[j,l] = c for all l
71
+ $$
72
+ $c$ is -1, 1 or 0 for $i=t$, $s$ or all others
73
+
74
+ """
75
+ log.info("Building constraints to find path from %s to %s", self.s, self.t)
76
+ variables = self.variables
77
+ nodes = [n for n in self.G.nodes]
78
+ m = len(nodes)
79
+ n = len(variables)
80
+ _cons = np.zeros((m, n), dtype=np.int8)
81
+ _rhs = np.zeros((m, 1), dtype=np.int8)
82
+ for node_index, k in enumerate(nodes):
83
+ if k == self.s:
84
+ _rhs[node_index, 0] = 1
85
+ elif k == self.t:
86
+ _rhs[node_index, 0] = -1
87
+ for l, (i, j) in enumerate(variables):
88
+ if i == j:
89
+ # self loops are not allowed
90
+ raise ValueError("Self loops are not allowed in ShortestPathModel")
91
+ # # ignore these edges because we can't go back to s or leave t
92
+ elif j == self.s:
93
+ continue
94
+ elif i == self.t:
95
+ continue
96
+ i_index = nodes.index(i)
97
+ j_index = nodes.index(j)
98
+ _cons[i_index, l] = 1
99
+ _cons[j_index, l] = -1
100
+ log.info("LHS shape %s RHS shape %s", _cons.shape, _rhs.shape)
101
+ log.info("checksum %f min %f", np.sum(_cons), np.min(_cons))
102
+ assert np.sum(_rhs) == 0
103
+ return _cons, np.squeeze(_rhs)
104
+
105
+ def buildObjective(self) -> Tuple[np.ndarray, np.ndarray]:
106
+ r"""
107
+ Objective:
108
+ $\min sum_ij w_ij x_ij$
109
+
110
+ """
111
+ variables = self.variables
112
+ G = self.G
113
+ nodes = G.nodes
114
+ m, n = len(nodes), len(variables)
115
+ _obj = [0 for i in range(n)]
116
+ for index, name in enumerate(variables):
117
+ i, j = name
118
+ _obj[index] = v = G.get_edge_data(i, j)["weight"]
119
+ assert not np.isnan(v), f"Got a NaN at {i, j}"
120
+ J = np.zeros((n, n))
121
+ return np.array(_obj), J
122
+
123
+ def decode(self, solution : np.ndarray) -> Dict:
124
+ """
125
+ Convert a solution to this model into a path, which is
126
+ a dictionary with each edge described by key, value pairs.
127
+
128
+ """
129
+ variables = self.variables
130
+
131
+ lhs, rhs = self.constraints
132
+ upper_thresh = max(solution)
133
+ lower_thresh = 0
134
+ while upper_thresh - lower_thresh > 1e-6:
135
+ log.info("Lower Value: %f Upper Value %f", lower_thresh, upper_thresh)
136
+ thresh = (lower_thresh + upper_thresh) / 2
137
+ nx_path = None
138
+ G = nx.DiGraph()
139
+ for (i, j), value in zip(variables, solution):
140
+ if value > thresh:
141
+ G.add_edge(i, j)
142
+ path = {}
143
+ try:
144
+ nx_path = nx.shortest_path(G, self.s, self.t)
145
+ upper_thresh = thresh
146
+ lower_thresh = thresh
147
+ except (nx.exception.NodeNotFound, nx.NetworkXAlgorithmError) as err:
148
+ lower_thresh = thresh
149
+ if nx_path is None:
150
+ raise RuntimeError(f"Solution does not describe path from {self.s} to {self.t}")
151
+ path = {}
152
+ for i, v in enumerate(nx_path):
153
+ path[nx_path[i-1]] = v
154
+ if self.t in path:
155
+ del path[self.t]
156
+ return path
157
+
@@ -11,6 +11,7 @@ import numpy as np
11
11
 
12
12
  from eqc_models import QuadraticModel
13
13
  from eqc_models.solvers.qciclient import Dirac3CloudSolver
14
+ from eqc_models.solvers.eqcdirect import Dirac3DirectSolver
14
15
 
15
16
 
16
17
  class ClassifierBase(QuadraticModel):
@@ -18,12 +19,25 @@ class ClassifierBase(QuadraticModel):
18
19
  self,
19
20
  relaxation_schedule=2,
20
21
  num_samples=1,
22
+ solver_access="cloud",
23
+ ip_addr=None,
24
+ port=None,
21
25
  ):
22
26
 
23
27
  super(self).__init__(None, None, None)
24
28
 
25
29
  self.relaxation_schedule = relaxation_schedule
26
30
  self.num_samples = num_samples
31
+
32
+ assert solver_access in ["cloud", "direct"]
33
+
34
+ if solver_access == "direct":
35
+ assert ip_addr is not None, "ip_addr should be set when using direct solver!"
36
+ assert port is not None,"port should be set when using direct solver!"
37
+
38
+ self.solver_access = solver_access
39
+ self.ip_addr = ip_addr
40
+ self.port = port
27
41
  self.params = None
28
42
  self.X_train = None
29
43
  self.y_train = None
@@ -53,18 +67,30 @@ class ClassifierBase(QuadraticModel):
53
67
  return
54
68
 
55
69
  def solve(self):
56
- solver = Dirac3CloudSolver()
70
+
71
+ if self.solver_access == "direct":
72
+ solver = Dirac3DirectSolver()
73
+ solver.connect(self.ip_addr, self.port)
74
+ else:
75
+ solver = Dirac3CloudSolver()
76
+
57
77
  response = solver.solve(
58
78
  self,
59
79
  sum_constraint=self._sum_constraint,
60
80
  relaxation_schedule=self.relaxation_schedule,
61
- solution_precision=1,
81
+ solution_precision=None,
62
82
  num_samples=self.num_samples,
63
83
  )
64
84
 
65
- min_id = np.argmin(response["results"]["energies"])
66
-
67
- sol = response["results"]["solutions"][min_id]
85
+ if self.solver_access == "cloud":
86
+ energies = response["results"]["energies"]
87
+ solutions = response["results"]["solutions"]
88
+ elif self.solver_access == "direct":
89
+ energies = response["energy"]
90
+ solutions = response["solution"]
91
+
92
+ min_id = np.argmin(energies)
93
+ sol = solutions[min_id]
68
94
 
69
95
  print(response)
70
96
 
@@ -94,6 +94,12 @@ class QBoostClassifier(ClassifierBase):
94
94
 
95
95
  num_samples: Number of samples used by Dirac-3; default: 1.
96
96
 
97
+ solver_access: Solver access type: cloud or direct; default: cloud.
98
+
99
+ ip_addr: IP address of the device when direct access is used; default: None.
100
+
101
+ port: Port number of the device when direct access is used; default: None.
102
+
97
103
  lambda_coef: A penalty multiplier; default: 0.
98
104
 
99
105
  weak_cls_schedule: Weak classifier schedule. Is either 1, 2,
@@ -155,6 +161,9 @@ class QBoostClassifier(ClassifierBase):
155
161
  self,
156
162
  relaxation_schedule=2,
157
163
  num_samples=1,
164
+ solver_access="cloud",
165
+ ip_addr=None,
166
+ port=None,
158
167
  lambda_coef=0,
159
168
  weak_cls_schedule=2,
160
169
  weak_cls_type="lg",
@@ -172,9 +181,13 @@ class QBoostClassifier(ClassifierBase):
172
181
  "multi_processing_shm",
173
182
  "sequential",
174
183
  ]
175
-
184
+ assert solver_access in ["cloud", "direct"]
185
+
176
186
  self.relaxation_schedule = relaxation_schedule
177
187
  self.num_samples = num_samples
188
+ self.solver_access = solver_access
189
+ self.ip_addr = ip_addr
190
+ self.port = port
178
191
  self.lambda_coef = lambda_coef
179
192
  self.weak_cls_schedule = weak_cls_schedule
180
193
  self.weak_cls_type = weak_cls_type
@@ -24,6 +24,12 @@ class QSVMClassifier(ClassifierBase):
24
24
 
25
25
  num_samples: Number of samples used by Dirac-3; default: 1.
26
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.
32
+
27
33
  lambda_coef: The penalty multipler
28
34
 
29
35
  Examples
@@ -67,12 +73,20 @@ class QSVMClassifier(ClassifierBase):
67
73
  self,
68
74
  relaxation_schedule=1,
69
75
  num_samples=1,
76
+ solver_access="cloud",
77
+ ip_addr=None,
78
+ port=None,
70
79
  lambda_coef=1.0,
71
80
  ):
72
81
  super(QSVMClassifier).__init__()
73
82
 
83
+ assert solver_access in ["cloud", "direct"]
84
+
74
85
  self.relaxation_schedule = relaxation_schedule
75
86
  self.num_samples = num_samples
87
+ self.solver_access = solver_access
88
+ self.ip_addr = ip_addr
89
+ self.port = port
76
90
  self.lambda_coef = lambda_coef
77
91
  self.fea_scaler = MinMaxScaler(feature_range=(-1, 1))
78
92
 
@@ -199,6 +213,12 @@ class QSVMClassifierDual(ClassifierBase):
199
213
 
200
214
  num_samples: Number of samples used by Dirac-3; default: 1.
201
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.
221
+
202
222
  upper_limit: Coefficient upper limit; a regularization parameter;
203
223
  default: 1.0.
204
224
 
@@ -253,6 +273,9 @@ class QSVMClassifierDual(ClassifierBase):
253
273
  self,
254
274
  relaxation_schedule=2,
255
275
  num_samples=1,
276
+ solver_access="cloud",
277
+ ip_addr=None,
278
+ port=None,
256
279
  upper_limit=1.0,
257
280
  gamma=1.0,
258
281
  eta=1.0,
@@ -260,8 +283,13 @@ class QSVMClassifierDual(ClassifierBase):
260
283
  ):
261
284
  super(QSVMClassifierDual).__init__()
262
285
 
286
+ assert solver_access in ["cloud", "direct"]
287
+
263
288
  self.relaxation_schedule = relaxation_schedule
264
289
  self.num_samples = num_samples
290
+ self.solver_access = solver_access
291
+ self.ip_addr = ip_addr
292
+ self.port = port
265
293
  self.upper_limit = upper_limit
266
294
  self.gamma = gamma
267
295
  self.eta = eta
@@ -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
@@ -2,6 +2,11 @@ import networkx as nx
2
2
  from eqc_models.base import ConstrainedPolynomialModel
3
3
 
4
4
  class ProcessModel:
5
+ """
6
+ Given a directed graph $G$ that describes a process flow, optimize the
7
+ flow.
8
+
9
+ """
5
10
  def __init__(self, G : nx.DiGraph):
6
11
  self.G = G
7
12
 
@@ -10,4 +15,4 @@ class ProcessModel:
10
15
  """ Build process constraints from the graph """
11
16
 
12
17
  def constraints(self) -> Tuple[np.ndarray]:
13
- """ """
18
+ pass
@@ -14,4 +14,4 @@ class ModelPredictiveControl(ProcessModel):
14
14
  raise NotImplementedError("subclass must implement processArgs")
15
15
 
16
16
  def constraints(self) -> Tuple[np.ndarray]:
17
-
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)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eqc-models
3
- Version: 0.11.1
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"
@@ -0,0 +1,65 @@
1
+ eqc_models-0.12.0.data/platlib/compile_extensions.py,sha256=ivFZ87WFzBITU7IwK_72C41MDNMortJIF8tKevm2aW4,1946
2
+ eqc_models-0.12.0.data/platlib/eqc_models/__init__.py,sha256=WPUijJz2-4UZU-ZTqBofDc-Yaah24geHdmF16SkwIj4,683
3
+ eqc_models-0.12.0.data/platlib/eqc_models/decoding.py,sha256=G3JgbIFzvZ3DIKW0kZ1JeTMIZmrc8hy9kzdbX2Xv5Og,637
4
+ eqc_models-0.12.0.data/platlib/eqc_models/algorithms/__init__.py,sha256=lzQoMMSs2QTqp5suEYNvcQaSEN16d0LwIsZ1mRstumU,135
5
+ eqc_models-0.12.0.data/platlib/eqc_models/algorithms/base.py,sha256=qfQQTwuVyewn7Qpg1_SVoD_7TsdA8vdwSKGqOeZSmNI,204
6
+ eqc_models-0.12.0.data/platlib/eqc_models/algorithms/penaltymultiplier.py,sha256=SndGxCZDS3JTaxFOPJpTBumFdIKcB0dKwSHwfl_BI6o,7845
7
+ eqc_models-0.12.0.data/platlib/eqc_models/allocation/__init__.py,sha256=op_udrapTlWrakTuQId3M0ggo-Y1w4nGJLPcYKOQ-8I,239
8
+ eqc_models-0.12.0.data/platlib/eqc_models/allocation/allocation.py,sha256=PAQn4M75Zegeoy0i6r3hycWs4TKeRglHk05TvwZOoLk,15506
9
+ eqc_models-0.12.0.data/platlib/eqc_models/allocation/portbase.py,sha256=BTnYYduHydPbrE2yQr_Sgv3XJACH_GpIJstuMrfGqCU,3269
10
+ eqc_models-0.12.0.data/platlib/eqc_models/allocation/portmomentum.py,sha256=oMod63rNDC-01dLZjmhUb24SN3_GVgfc6CItgQL_obI,3756
11
+ eqc_models-0.12.0.data/platlib/eqc_models/assignment/__init__.py,sha256=WDlTjWGu75UTxuNUPGNVGoMaYvYILWzZOuS-o72n054,160
12
+ eqc_models-0.12.0.data/platlib/eqc_models/assignment/qap.py,sha256=WMiQQmTORsgi2w7kbmMA1xo-93dESLECWqYTF-zkmTs,2963
13
+ eqc_models-0.12.0.data/platlib/eqc_models/assignment/resource.py,sha256=Ux9e3Badty6bFMqRaLKAGbVRUtb1k1r1_E_2ajOhgb4,6883
14
+ eqc_models-0.12.0.data/platlib/eqc_models/assignment/setpartition.py,sha256=5SQxF_ZlQk4ubWf5_3TgL83k01hAakUP-5AydlD-BvE,161
15
+ eqc_models-0.12.0.data/platlib/eqc_models/base/__init__.py,sha256=wKBppDk1lBiDvGOFnNpzu4lh7n4dQiyd_x3lNQJumTw,2952
16
+ eqc_models-0.12.0.data/platlib/eqc_models/base/base.py,sha256=tL6z0MW4ffMKWlozZ0CH4soTiKxSlMXqyVDctaA110U,6405
17
+ eqc_models-0.12.0.data/platlib/eqc_models/base/constraints.py,sha256=KMPyCdt_8GMWLnVEdpzw1T1WqXm2f7Lh629ClUH7XDY,8271
18
+ eqc_models-0.12.0.data/platlib/eqc_models/base/operators.py,sha256=9nCeN6fRP-_YBfs-Gm57D-O_376qcOQiqGDuVlSlf00,7392
19
+ eqc_models-0.12.0.data/platlib/eqc_models/base/polyeval.c,sha256=bocwtLflgApAjP2W67qZSJAXusFfeCANi3aj486rcPA,476034
20
+ eqc_models-0.12.0.data/platlib/eqc_models/base/polyeval.cpython-310-darwin.so,sha256=nguZ04tigmotFBAmsz1DXha7X7G97pBSGoGDIXMOL5I,108736
21
+ eqc_models-0.12.0.data/platlib/eqc_models/base/polyeval.pyx,sha256=76Bf99Jt1_rLh5byrZxAjavE2F4_yCysirViqOBFIXw,2547
22
+ eqc_models-0.12.0.data/platlib/eqc_models/base/polynomial.py,sha256=FQA26ihFlwfHz9k9XP3qDM0hl5Ko4rtUxiXloj3ail4,13056
23
+ eqc_models-0.12.0.data/platlib/eqc_models/base/quadratic.py,sha256=IKjd-tL6pQosl217knS_ul2BXpk5a8ZZiSUzvKPg8S8,8082
24
+ eqc_models-0.12.0.data/platlib/eqc_models/base/results.py,sha256=P7m88UBA1xir8BOYvA51Cnftrdu7hnWuFqt3lUIEVO8,5831
25
+ eqc_models-0.12.0.data/platlib/eqc_models/combinatorics/__init__.py,sha256=BhzcVxwpWu2b4jIe0bmPzD5VmSyzwp0oW2q9iYx2IUs,167
26
+ eqc_models-0.12.0.data/platlib/eqc_models/combinatorics/setcover.py,sha256=T5hXoE9Ecw3mTHPLmifBwTzpF_4MhoCUgo2rkSOWt5s,3396
27
+ eqc_models-0.12.0.data/platlib/eqc_models/combinatorics/setpartition.py,sha256=ZD69kgEYSU3KWnx0b4MVCP8XSxbA_VCXOW22_Yssl_M,6254
28
+ eqc_models-0.12.0.data/platlib/eqc_models/graph/__init__.py,sha256=PUSoVwzyZSHAbTEBfdakeRxWlkPeeGD1xfyY8OmMxYE,300
29
+ eqc_models-0.12.0.data/platlib/eqc_models/graph/base.py,sha256=K9d7hLgLuBtywEdK9Rz1dUV70Xtf-oVrwqtHyzXK7k4,2117
30
+ eqc_models-0.12.0.data/platlib/eqc_models/graph/hypergraph.py,sha256=ABvutT0NOdIEpUF4TjUzboE4Y_J5iUZyj6-AzKr4R28,13268
31
+ eqc_models-0.12.0.data/platlib/eqc_models/graph/maxcut.py,sha256=o8xVsAwTa9jcpmsIoCQ5z7HSstVdraT8TENomdT519o,4132
32
+ eqc_models-0.12.0.data/platlib/eqc_models/graph/maxkcut.py,sha256=rEDBjto2MbuPh4c0RwTOZoVffKgcriqHNOZAIuBlclQ,4654
33
+ eqc_models-0.12.0.data/platlib/eqc_models/graph/partition.py,sha256=HMpRRipLp14x8pHucY-g6fU7v0PGoy1pf_KpzbanfD0,5800
34
+ eqc_models-0.12.0.data/platlib/eqc_models/graph/shortestpath.py,sha256=5BIvPmYW43juxEDVtIAAlvK6hMP5Kj-fCB7SBKgY124,4988
35
+ eqc_models-0.12.0.data/platlib/eqc_models/ml/__init__.py,sha256=CLfraacr0FrD5ynxlNB6cyNy0lpbavcQT45TvkDrNvY,369
36
+ eqc_models-0.12.0.data/platlib/eqc_models/ml/classifierbase.py,sha256=6W1iMlcorNtOPLS7ui8ED9UQ-xgFBK1yh_besy4swyM,3117
37
+ eqc_models-0.12.0.data/platlib/eqc_models/ml/classifierqboost.py,sha256=oxYnex7Z_iXglupqmMN9bK6gU1DxKcHOo03fLCmELfQ,19456
38
+ eqc_models-0.12.0.data/platlib/eqc_models/ml/classifierqsvm.py,sha256=ELKAdOMExeNjJIJCHd28bf7xQYBI2TpQDGkifldThkU,12120
39
+ eqc_models-0.12.0.data/platlib/eqc_models/ml/clustering.py,sha256=KD8mv_xY9-pRGKDRgeLDO3e38cjftzca4SUBvN4__-I,9522
40
+ eqc_models-0.12.0.data/platlib/eqc_models/ml/clusteringbase.py,sha256=NSoOS_MJpiDrblJ3nQPSFXthJHsBWmTx8RJGhMexNUE,2642
41
+ eqc_models-0.12.0.data/platlib/eqc_models/ml/cvqboost_hamiltonian.pyx,sha256=3PMmEJ_xfmmWXGfire0t-WASnmKj6-CblufgQ2NTARo,2111
42
+ eqc_models-0.12.0.data/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.c,sha256=ZoKgm_uGjTewhk4W6s-x8QoFuZO0KVkxILIFh6JKsoI,1851
43
+ eqc_models-0.12.0.data/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.h,sha256=aOImMG5pziUnZxGpDXyWjLrvcY7ZdsczwwSQ2ay4T88,272
44
+ eqc_models-0.12.0.data/platlib/eqc_models/ml/decomposition.py,sha256=Cmw9P-Xv_lzbyD0f-zNjJFX9H0ah--ZLyXUSRYXdfw0,9509
45
+ eqc_models-0.12.0.data/platlib/eqc_models/ml/forecast.py,sha256=fFcBxQK9ZryfEuyvlr9HXicHoZRzLFybimYYttzhI9E,7403
46
+ eqc_models-0.12.0.data/platlib/eqc_models/ml/forecastbase.py,sha256=s-6nUMvtYqG07r7MmmkFVj8_QqgeGkD-HVoEEDTE2bk,3654
47
+ eqc_models-0.12.0.data/platlib/eqc_models/ml/regressor.py,sha256=LA1woXCnefG0wfoOxilX1kszgCUmfNcbQgs_WZ4Ai0o,5683
48
+ eqc_models-0.12.0.data/platlib/eqc_models/ml/regressorbase.py,sha256=H5E8-8pUji1oH5JRdS37LJQoHuKt2JU8eXCZp-ZaEM4,2109
49
+ eqc_models-0.12.0.data/platlib/eqc_models/ml/reservoir.py,sha256=cPRvpCaWLYTBkui35jCssHcOPQgSQZallrG6Ac9djVI,2827
50
+ eqc_models-0.12.0.data/platlib/eqc_models/process/base.py,sha256=QmwbPRc9w9Yr7cwPvdnV6LBdgajif_8WGYGfwApvO34,443
51
+ eqc_models-0.12.0.data/platlib/eqc_models/process/mpc.py,sha256=V7RlA6t08IayV-VKkpK4mC01Lvk3ZTD-HlFYk60snks,645
52
+ eqc_models-0.12.0.data/platlib/eqc_models/sequence/__init__.py,sha256=VXlYufO3GYFsM00oii9Cite2WsQEF8XTwRcjLPH_Zlg,92
53
+ eqc_models-0.12.0.data/platlib/eqc_models/sequence/tsp.py,sha256=YM641FTyK5NkgRGxHrU1QmMkEU0gf77nEmIElTqa6Qw,7680
54
+ eqc_models-0.12.0.data/platlib/eqc_models/solvers/__init__.py,sha256=OLwg3lxMh2rali4lovIxnR-CA1CISNnD5LRgCv48cck,432
55
+ eqc_models-0.12.0.data/platlib/eqc_models/solvers/eqcdirect.py,sha256=VMMQzcW2VmalJ8__c_8hbygL0Kx0NDsL6HCi9l2T5-o,2115
56
+ eqc_models-0.12.0.data/platlib/eqc_models/solvers/qciclient.py,sha256=73m6TNqwxvtgeVHKcym87UXqkSAAj4UrVeDRKlr7ys0,27362
57
+ eqc_models-0.12.0.data/platlib/eqc_models/utilities/__init__.py,sha256=SI2U7JKmPWSiq-F1WcSyfd7l9V6nbOZv_p8quMAZaT0,340
58
+ eqc_models-0.12.0.data/platlib/eqc_models/utilities/fileio.py,sha256=alWPTfjGFx6Iio9HZAAWtYcLmZsBBifg6S6_YbFMQhk,1088
59
+ eqc_models-0.12.0.data/platlib/eqc_models/utilities/polynomial.py,sha256=blXfu7Ehz9lT4nEmIinRzJOL27_qUHSbQ57zxmwDJCA,4735
60
+ eqc_models-0.12.0.data/platlib/eqc_models/utilities/qplib.py,sha256=Do-MjmCFdI5HyDOAjfoz4_5lugySLMBlMAWDLUWx2OA,15796
61
+ eqc_models-0.12.0.dist-info/licenses/LICENSE.txt,sha256=8eh0oqsNNVR1Jk-13gkqRRSo2axtUU5kp2KzH4f9u3U,11354
62
+ eqc_models-0.12.0.dist-info/METADATA,sha256=LlwLohomCtAUlHu7eVM5ZicCPxrgu0YI4r8NWfmGT2Q,7087
63
+ eqc_models-0.12.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
64
+ eqc_models-0.12.0.dist-info/top_level.txt,sha256=9ZfFeKNEvkRlKWoUnfcZ9TzmTdgdsuPEnTPy11Hqf4Q,30
65
+ eqc_models-0.12.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.1.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,6 +0,0 @@
1
- # (C) Quantum Computing Inc., 2024.
2
-
3
- from .maxcut import MaxCutModel
4
- from .partition import GraphPartitionModel
5
-
6
- __all__ = ["MaxCutModel", "GraphPartitionModel"]