eqc-models 0.10.0__py3-none-any.whl → 0.10.3__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.
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/__init__.py +2 -1
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/algorithms/penaltymultiplier.py +20 -7
- eqc_models-0.10.3.data/platlib/eqc_models/assignment/setpartition.py +4 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/base/base.py +44 -4
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/base/polyeval.c +163 -163
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/base/polyeval.cpython-310-darwin.so +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/base/polynomial.py +7 -3
- eqc_models-0.10.3.data/platlib/eqc_models/combinatorics/__init__.py +6 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/combinatorics/setcover.py +35 -17
- {eqc_models-0.10.0.data/platlib/eqc_models/assignment → eqc_models-0.10.3.data/platlib/eqc_models/combinatorics}/setpartition.py +2 -0
- eqc_models-0.10.3.data/platlib/eqc_models/graph/__init__.py +6 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/graph/maxkcut.py +26 -68
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/solvers/qciclient.py +11 -2
- {eqc_models-0.10.0.dist-info → eqc_models-0.10.3.dist-info}/METADATA +3 -2
- eqc_models-0.10.3.dist-info/RECORD +59 -0
- {eqc_models-0.10.0.dist-info → eqc_models-0.10.3.dist-info}/WHEEL +1 -1
- eqc_models-0.10.0.data/platlib/eqc_models/base.py +0 -115
- eqc_models-0.10.0.data/platlib/eqc_models/communitydetection.py +0 -25
- eqc_models-0.10.0.data/platlib/eqc_models/eqcdirectsolver.py +0 -61
- eqc_models-0.10.0.data/platlib/eqc_models/graph/__init__.py +0 -5
- eqc_models-0.10.0.data/platlib/eqc_models/graphs.py +0 -28
- eqc_models-0.10.0.data/platlib/eqc_models/maxcut.py +0 -113
- eqc_models-0.10.0.data/platlib/eqc_models/maxkcut.py +0 -185
- eqc_models-0.10.0.data/platlib/eqc_models/quadraticmodel.py +0 -131
- eqc_models-0.10.0.data/platlib/eqc_models/solvers/eqcdirect.py +0 -160
- eqc_models-0.10.0.dist-info/RECORD +0 -65
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/compile_extensions.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/algorithms/__init__.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/algorithms/base.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/allocation/__init__.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/allocation/allocation.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/allocation/portbase.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/allocation/portmomentum.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/assignment/__init__.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/assignment/qap.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/base/__init__.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/base/constraints.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/base/operators.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/base/polyeval.pyx +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/base/quadratic.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/decoding.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/graph/base.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/graph/hypergraph.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/graph/maxcut.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/graph/partition.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/ml/__init__.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/ml/classifierbase.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/ml/classifierqboost.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/ml/classifierqsvm.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/ml/clustering.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/ml/clusteringbase.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/ml/cvqboost_hamiltonian.pyx +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.c +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.h +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/ml/decomposition.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/ml/forecast.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/ml/forecastbase.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/ml/regressor.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/ml/regressorbase.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/ml/reservoir.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/sequence/__init__.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/sequence/tsp.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/solvers/__init__.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/utilities/__init__.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/utilities/fileio.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/utilities/polynomial.py +0 -0
- {eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/utilities/qplib.py +0 -0
- {eqc_models-0.10.0.dist-info → eqc_models-0.10.3.dist-info/licenses}/LICENSE.txt +0 -0
- {eqc_models-0.10.0.dist-info → eqc_models-0.10.3.dist-info}/top_level.txt +0 -0
|
Binary file
|
|
@@ -117,12 +117,15 @@ class PolynomialModel(PolynomialMixin, EqcModel):
|
|
|
117
117
|
|
|
118
118
|
@property
|
|
119
119
|
def qubo(self) -> QUBO:
|
|
120
|
+
polynomial = self.polynomial
|
|
121
|
+
coefficients = polynomial.coefficients
|
|
122
|
+
indices = polynomial.indices
|
|
120
123
|
try:
|
|
121
|
-
if np.all([len(
|
|
124
|
+
if np.all([len(indices[i]) == 2 for i in range(len(indices))]):
|
|
122
125
|
bin_n = 0
|
|
123
126
|
bits = []
|
|
124
|
-
C, J = self._quadratic_polynomial_to_qubo_coefficients(
|
|
125
|
-
|
|
127
|
+
C, J = self._quadratic_polynomial_to_qubo_coefficients(coefficients,
|
|
128
|
+
indices, self.n)
|
|
126
129
|
# upper_bound is an array of the maximum values each variable can take
|
|
127
130
|
upper_bound = self.upper_bound
|
|
128
131
|
if np.sum(upper_bound) != upper_bound.shape[0]:
|
|
@@ -158,6 +161,7 @@ class PolynomialModel(PolynomialMixin, EqcModel):
|
|
|
158
161
|
raise OperatorNotAvailableError("QUBO operator not available")
|
|
159
162
|
except OperatorNotAvailableError as e:
|
|
160
163
|
print(e)
|
|
164
|
+
raise
|
|
161
165
|
|
|
162
166
|
def _quadratic_polynomial_to_qubo_coefficients(self, coefficients, indices, num_variables):
|
|
163
167
|
"""
|
{eqc_models-0.10.0.data → eqc_models-0.10.3.data}/platlib/eqc_models/combinatorics/setcover.py
RENAMED
|
@@ -37,44 +37,61 @@ class SetCoverModel(ConstrainedQuadraticModel):
|
|
|
37
37
|
List of weights where each weight is the cost of choosing the subset
|
|
38
38
|
corresponding to the index of the weight.
|
|
39
39
|
|
|
40
|
+
|
|
40
41
|
>>> X = [set(['A', 'B']), set(['B', 'C']), set(['C'])]
|
|
41
42
|
>>> weights = [2, 2, 1]
|
|
42
43
|
>>> model = SetCoverModel(X, weights)
|
|
43
|
-
>>> model.penalty_multiplier =
|
|
44
|
+
>>> model.penalty_multiplier = 8
|
|
45
|
+
>>> lhs, rhs = model.constraints
|
|
46
|
+
>>> lhs
|
|
47
|
+
array([[ 1, 0, 0, 0, 0],
|
|
48
|
+
[ 1, 1, 0, -1, 0],
|
|
49
|
+
[ 0, 1, 1, 0, -1]])
|
|
44
50
|
>>> from eqc_models.solvers import Dirac3IntegerCloudSolver
|
|
45
51
|
>>> solver = Dirac3IntegerCloudSolver()
|
|
46
52
|
>>> response = solver.solve(model, relaxation_schedule=1, num_samples=5) #doctest: +ELLIPSIS
|
|
47
53
|
20...
|
|
48
54
|
>>> solutions = response["results"]["solutions"]
|
|
49
55
|
>>> solutions[0]
|
|
50
|
-
[1, 0, 1, 0, 0
|
|
51
|
-
>>> model.decode(solutions[0])
|
|
52
|
-
|
|
56
|
+
[1, 0, 1, 0, 0]
|
|
57
|
+
>>> selections = model.decode(solutions[0])
|
|
58
|
+
>>> assert {'B', 'A'} in selections
|
|
59
|
+
>>> assert {'C'} in selections
|
|
60
|
+
>>> assert len(selections) == 2
|
|
53
61
|
|
|
54
62
|
"""
|
|
55
63
|
|
|
56
64
|
def __init__(self, subsets, weights):
|
|
57
65
|
# ensure that X is ordered
|
|
58
|
-
self.
|
|
59
|
-
self.
|
|
66
|
+
self.S = S = list(subsets)
|
|
67
|
+
self.universal_set = U = set()
|
|
60
68
|
|
|
61
69
|
for x in subsets:
|
|
62
|
-
|
|
70
|
+
U.update(x)
|
|
63
71
|
# elements is sorted to maintain consistent output
|
|
64
|
-
elements = [a for a in
|
|
72
|
+
elements = [a for a in U]
|
|
65
73
|
elements.sort()
|
|
66
74
|
# constraints
|
|
67
75
|
A = []
|
|
68
76
|
b = []
|
|
69
|
-
variables = [f'x_{i}' for i in range(len(
|
|
77
|
+
variables = [f'x_{i}' for i in range(len(S))]
|
|
70
78
|
pos = 0
|
|
79
|
+
num_slacks = 0
|
|
80
|
+
slack_ub = []
|
|
71
81
|
for a in elements:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
82
|
+
num_sets = sum([1 if a in S[i] else 0 for i in range(len(S))])
|
|
83
|
+
assert num_sets >= 1, "Invalid subsets, check the universal set"
|
|
84
|
+
if num_sets > 1:
|
|
85
|
+
num_slacks += 1
|
|
86
|
+
slack_ub.append(num_sets-1)
|
|
87
|
+
for i, a in enumerate(elements):
|
|
88
|
+
constraint = [1 if a in S[j] else 0 for j in range(len(S))]
|
|
89
|
+
slacks = [0 for i in range(num_slacks)]
|
|
90
|
+
if slack_ub[i] > 0:
|
|
91
|
+
variables.append(f"s_{pos}")
|
|
92
|
+
slacks[pos] = -1
|
|
93
|
+
pos += 1
|
|
76
94
|
A.append(constraint + slacks)
|
|
77
|
-
pos += 1
|
|
78
95
|
b.append(1)
|
|
79
96
|
n = len(variables)
|
|
80
97
|
J = np.zeros((n, n))
|
|
@@ -83,11 +100,12 @@ class SetCoverModel(ConstrainedQuadraticModel):
|
|
|
83
100
|
# call the superclass constructor with the objective and constraints
|
|
84
101
|
super(SetCoverModel, self).__init__(h, J, np.array(A), np.array(b))
|
|
85
102
|
# set upper bound on the variables to be 1 for x_i and the length of X minus 1 for the slacks
|
|
86
|
-
|
|
103
|
+
slack_ub = [val for val in slack_ub if val > 0]
|
|
104
|
+
self.upper_bound = np.array([1 for i in range(len(weights))] + slack_ub)
|
|
87
105
|
|
|
88
106
|
def decode(self, solution) -> List:
|
|
89
107
|
xbar = []
|
|
90
|
-
for i in range(len(self.
|
|
108
|
+
for i in range(len(self.S)):
|
|
91
109
|
if solution[i] > 0.5:
|
|
92
|
-
xbar.append(self.
|
|
110
|
+
xbar.append(self.S[i])
|
|
93
111
|
return xbar
|
|
@@ -86,6 +86,8 @@ class SetPartitionModel(ConstrainedPolynomialModel):
|
|
|
86
86
|
b = np.ones((A.shape[0],))
|
|
87
87
|
n = A.shape[1]
|
|
88
88
|
|
|
89
|
+
self.upper_bound = np.ones((n,), np.int32)
|
|
90
|
+
|
|
89
91
|
# Define the linear objective function based on subset weights
|
|
90
92
|
self.linear_objective = np.array(weights).reshape((n, 1))
|
|
91
93
|
self.quad_objective = np.zeros((n, n)) #np.zeros_like(J)
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
# (C) Quantum Computing Inc., 2024.
|
|
2
|
+
from typing import Tuple
|
|
2
3
|
import numpy as np
|
|
3
4
|
import networkx as nx
|
|
4
5
|
from .base import NodeModel
|
|
6
|
+
from eqc_models.base.quadratic import ConstrainedQuadraticModel
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
class MaxKCutModel(ConstrainedQuadraticModel):
|
|
9
|
+
_objective = None
|
|
8
10
|
|
|
9
11
|
def __init__(self, G : nx.Graph, k : int):
|
|
10
|
-
|
|
12
|
+
self.G = G
|
|
11
13
|
self.k = k
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
self
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
A, b = self._build_constraints()
|
|
15
|
+
c, J = self.costFunction()
|
|
16
|
+
ConstrainedQuadraticModel.__init__(self, c, J, A, b)
|
|
17
|
+
if k < 3:
|
|
18
|
+
raise ValueError("k must be greater than 2")
|
|
19
|
+
n = len(G.nodes) * k
|
|
20
|
+
self.upper_bound = np.ones((n,))
|
|
21
|
+
|
|
18
22
|
def decode(self, solution: np.ndarray) -> np.ndarray:
|
|
19
23
|
""" Override the default decoding to use a the max cut metric to determine a solution """
|
|
20
24
|
|
|
@@ -22,7 +26,8 @@ class MaxKCutModel(NodeModel):
|
|
|
22
26
|
# rather than the same cutoff per node, use the max value per partition
|
|
23
27
|
decoded_solution = np.zeros_like(solution, dtype=np.int32)
|
|
24
28
|
k = self.k
|
|
25
|
-
|
|
29
|
+
G = self.G
|
|
30
|
+
for i, u in enumerate(G.nodes):
|
|
26
31
|
idx = slice(k*i, k*(i+1))
|
|
27
32
|
spins = solution[idx]
|
|
28
33
|
mx = np.max(spins)
|
|
@@ -35,9 +40,9 @@ class MaxKCutModel(NodeModel):
|
|
|
35
40
|
def partition(self, solution):
|
|
36
41
|
""" Return a dictionary with the partition number of each node """
|
|
37
42
|
k = self.k
|
|
38
|
-
|
|
43
|
+
G = self.G
|
|
39
44
|
partition_num = {}
|
|
40
|
-
for i, u in enumerate(
|
|
45
|
+
for i, u in enumerate(G.nodes):
|
|
41
46
|
for j in range(k):
|
|
42
47
|
if solution[i*k+j] == 1:
|
|
43
48
|
partition_num[u] = j+1
|
|
@@ -50,10 +55,10 @@ class MaxKCutModel(NodeModel):
|
|
|
50
55
|
cut_size += 1
|
|
51
56
|
return cut_size
|
|
52
57
|
|
|
53
|
-
def
|
|
58
|
+
def costFunction(self) -> Tuple:
|
|
54
59
|
|
|
55
|
-
node_map = self.variables
|
|
56
60
|
G = self.G
|
|
61
|
+
node_map = list(G.nodes)
|
|
57
62
|
m = len(G.nodes)
|
|
58
63
|
n = self.k * m
|
|
59
64
|
# construct the quadratic portion of the objective
|
|
@@ -70,12 +75,12 @@ class MaxKCutModel(NodeModel):
|
|
|
70
75
|
idx1 = ibase + incr1
|
|
71
76
|
idx2 = jbase + incr2
|
|
72
77
|
objective[idx1, idx2] += -1
|
|
73
|
-
|
|
78
|
+
return (np.zeros((n, 1)), objective)
|
|
74
79
|
|
|
75
80
|
def _build_constraints(self):
|
|
76
81
|
|
|
77
|
-
node_map = self.variables
|
|
78
82
|
G = self.G
|
|
83
|
+
node_map = list(G.nodes)
|
|
79
84
|
m = len(G.nodes)
|
|
80
85
|
n = self.k * m
|
|
81
86
|
|
|
@@ -86,78 +91,31 @@ class MaxKCutModel(NodeModel):
|
|
|
86
91
|
i = node_map.index(u)
|
|
87
92
|
ibase = i * self.k
|
|
88
93
|
A[i, ibase:ibase+self.k] = 1
|
|
89
|
-
|
|
90
|
-
self.rhs = b
|
|
91
|
-
|
|
92
|
-
def build(self, multiplier=None):
|
|
93
|
-
""" Create the constraints and objective and Hamiltonian """
|
|
94
|
-
|
|
95
|
-
# there are k * m variables in this problem where m is the number of nodes in the graph
|
|
96
|
-
node_map = self.variables
|
|
97
|
-
G = self.G
|
|
98
|
-
m = len(G.nodes)
|
|
99
|
-
n = self.k * m
|
|
100
|
-
self.upper_bound = np.ones((n,))
|
|
101
|
-
|
|
102
|
-
self._build_objective()
|
|
103
|
-
if multiplier is None:
|
|
104
|
-
multiplier = np.max(np.abs(self._objective[1]))
|
|
105
|
-
self._build_constraints()
|
|
106
|
-
|
|
107
|
-
self._C, self._J = self.buildH(multiplier)
|
|
108
|
-
self.sum_constraint = m
|
|
109
|
-
|
|
110
|
-
def buildH(self, multiplier):
|
|
111
|
-
""" Combine the objective and penalties using the multiplier """
|
|
112
|
-
|
|
113
|
-
objC, objJ = self.objective
|
|
114
|
-
lhs, rhs = self.constraints
|
|
115
|
-
Pq = lhs.T@lhs
|
|
116
|
-
Pl = -2 * rhs.T@lhs
|
|
117
|
-
offset = rhs.T@rhs
|
|
118
|
-
n = self.n
|
|
119
|
-
J = np.zeros((n, n), np.float32)
|
|
120
|
-
C = np.zeros([n, 1], np.float32)
|
|
121
|
-
C += objC
|
|
122
|
-
J[:,:] += objJ
|
|
123
|
-
C += multiplier * Pl.reshape((n, 1))
|
|
124
|
-
J[:,:] += multiplier * Pq
|
|
125
|
-
return C, J
|
|
94
|
+
return A, b
|
|
126
95
|
|
|
127
96
|
@property
|
|
128
97
|
def constraints(self):
|
|
129
98
|
""" Return LHS, RHS in numpy matrix format """
|
|
130
|
-
|
|
131
|
-
self.build()
|
|
99
|
+
|
|
132
100
|
return self.lhs, self.rhs
|
|
133
101
|
|
|
134
102
|
@property
|
|
135
103
|
def objective(self):
|
|
136
104
|
""" Return the quadratic objective as NxN+1 matrix """
|
|
137
105
|
|
|
138
|
-
if self._objective is None:
|
|
139
|
-
self.build()
|
|
140
106
|
return self._objective
|
|
141
107
|
|
|
142
|
-
@property
|
|
143
|
-
def H(self):
|
|
144
|
-
""" Return the Hamiltonian as parts C, J """
|
|
145
|
-
|
|
146
|
-
if self._C is None:
|
|
147
|
-
self.build()
|
|
148
|
-
return self._C, self._J
|
|
149
|
-
|
|
150
108
|
class WeightedMaxKCutModel(MaxKCutModel):
|
|
151
109
|
|
|
152
110
|
def __init__(self, G: nx.Graph, k: int, weight_label : str = "weight"):
|
|
153
|
-
super().__init__(G, k)
|
|
111
|
+
super(WeightedMaxCutModel).__init__(G, k)
|
|
154
112
|
|
|
155
113
|
self.weight_label = weight_label
|
|
156
114
|
|
|
157
115
|
def _build_objective(self):
|
|
158
116
|
|
|
159
|
-
node_map = self.variables
|
|
160
117
|
G = self.G
|
|
118
|
+
node_map = list(G.nodes)
|
|
161
119
|
m = len(G.nodes)
|
|
162
120
|
n = self.k * m
|
|
163
121
|
# construct the quadratic portion of the objective
|
|
@@ -174,7 +132,7 @@ class WeightedMaxKCutModel(MaxKCutModel):
|
|
|
174
132
|
idx1 = ibase + incr1
|
|
175
133
|
idx2 = jbase + incr2
|
|
176
134
|
objective[idx1, idx2] += G[u][v][self.weight_label]
|
|
177
|
-
|
|
135
|
+
return (np.zeros((n, 1)), objective)
|
|
178
136
|
|
|
179
137
|
def getCutSize(self, partition):
|
|
180
138
|
cut_size = 0
|
|
@@ -68,10 +68,19 @@ class QciClientMixin:
|
|
|
68
68
|
client = QciClient(url=self.url, api_token=self.api_token)
|
|
69
69
|
return client
|
|
70
70
|
|
|
71
|
+
def getMetrics(self, job_id : str) -> Dict:
|
|
72
|
+
"""
|
|
73
|
+
Returns a dictionary containing the job metrics.
|
|
74
|
+
|
|
75
|
+
"""
|
|
76
|
+
client = self.client
|
|
77
|
+
metrics = client.get_job_metrics(job_id=job_id)
|
|
78
|
+
return metrics
|
|
79
|
+
|
|
71
80
|
class Dirac1Mixin:
|
|
72
81
|
sampler_type = "dirac-1"
|
|
73
82
|
requires_operator = "qubo"
|
|
74
|
-
max_upper_bound =
|
|
83
|
+
max_upper_bound = 205 # log encoding beyond this level has inherent issues
|
|
75
84
|
job_params_names = ["num_samples", "alpha", "atol"]
|
|
76
85
|
|
|
77
86
|
class QuboSolverMixin:
|
|
@@ -141,7 +150,7 @@ class Dirac3Mixin:
|
|
|
141
150
|
poly_indices = polynomial.indices
|
|
142
151
|
data = []
|
|
143
152
|
# must find these attributes of the polynomial before uploading
|
|
144
|
-
max_degree =
|
|
153
|
+
max_degree = 2
|
|
145
154
|
min_degree = len(poly_indices[-1])
|
|
146
155
|
num_variables = 0
|
|
147
156
|
for i in range(len(poly_coeffs)):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: eqc-models
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.3
|
|
4
4
|
Summary: Optimization and ML modeling package targeting EQC devices
|
|
5
5
|
Author: Quantum Computing Inc.
|
|
6
6
|
Author-email: support@quantumcomputinginc.com
|
|
@@ -22,6 +22,7 @@ Provides-Extra: dev
|
|
|
22
22
|
Requires-Dist: pytest<8,>=7.1.0; extra == "dev"
|
|
23
23
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
24
24
|
Requires-Dist: sphinx_rtd_theme<2,>=1.3.0; extra == "dev"
|
|
25
|
+
Dynamic: license-file
|
|
25
26
|
|
|
26
27
|
# EQC Models
|
|
27
28
|
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
eqc_models-0.10.3.data/platlib/compile_extensions.py,sha256=ivFZ87WFzBITU7IwK_72C41MDNMortJIF8tKevm2aW4,1946
|
|
2
|
+
eqc_models-0.10.3.data/platlib/eqc_models/__init__.py,sha256=WPUijJz2-4UZU-ZTqBofDc-Yaah24geHdmF16SkwIj4,683
|
|
3
|
+
eqc_models-0.10.3.data/platlib/eqc_models/decoding.py,sha256=G3JgbIFzvZ3DIKW0kZ1JeTMIZmrc8hy9kzdbX2Xv5Og,637
|
|
4
|
+
eqc_models-0.10.3.data/platlib/eqc_models/algorithms/__init__.py,sha256=lzQoMMSs2QTqp5suEYNvcQaSEN16d0LwIsZ1mRstumU,135
|
|
5
|
+
eqc_models-0.10.3.data/platlib/eqc_models/algorithms/base.py,sha256=qfQQTwuVyewn7Qpg1_SVoD_7TsdA8vdwSKGqOeZSmNI,204
|
|
6
|
+
eqc_models-0.10.3.data/platlib/eqc_models/algorithms/penaltymultiplier.py,sha256=SndGxCZDS3JTaxFOPJpTBumFdIKcB0dKwSHwfl_BI6o,7845
|
|
7
|
+
eqc_models-0.10.3.data/platlib/eqc_models/allocation/__init__.py,sha256=op_udrapTlWrakTuQId3M0ggo-Y1w4nGJLPcYKOQ-8I,239
|
|
8
|
+
eqc_models-0.10.3.data/platlib/eqc_models/allocation/allocation.py,sha256=PAQn4M75Zegeoy0i6r3hycWs4TKeRglHk05TvwZOoLk,15506
|
|
9
|
+
eqc_models-0.10.3.data/platlib/eqc_models/allocation/portbase.py,sha256=BTnYYduHydPbrE2yQr_Sgv3XJACH_GpIJstuMrfGqCU,3269
|
|
10
|
+
eqc_models-0.10.3.data/platlib/eqc_models/allocation/portmomentum.py,sha256=oMod63rNDC-01dLZjmhUb24SN3_GVgfc6CItgQL_obI,3756
|
|
11
|
+
eqc_models-0.10.3.data/platlib/eqc_models/assignment/__init__.py,sha256=CX_QYl8P1meajV8gcVs6hm07VhoLVe8uu436t7-1XQo,86
|
|
12
|
+
eqc_models-0.10.3.data/platlib/eqc_models/assignment/qap.py,sha256=WMiQQmTORsgi2w7kbmMA1xo-93dESLECWqYTF-zkmTs,2963
|
|
13
|
+
eqc_models-0.10.3.data/platlib/eqc_models/assignment/setpartition.py,sha256=5SQxF_ZlQk4ubWf5_3TgL83k01hAakUP-5AydlD-BvE,161
|
|
14
|
+
eqc_models-0.10.3.data/platlib/eqc_models/base/__init__.py,sha256=RwZguuucmsuOSVqfPLBqj-wzinBOzcgO-2ifFU-DCqg,2885
|
|
15
|
+
eqc_models-0.10.3.data/platlib/eqc_models/base/base.py,sha256=tL6z0MW4ffMKWlozZ0CH4soTiKxSlMXqyVDctaA110U,6405
|
|
16
|
+
eqc_models-0.10.3.data/platlib/eqc_models/base/constraints.py,sha256=KMPyCdt_8GMWLnVEdpzw1T1WqXm2f7Lh629ClUH7XDY,8271
|
|
17
|
+
eqc_models-0.10.3.data/platlib/eqc_models/base/operators.py,sha256=9nCeN6fRP-_YBfs-Gm57D-O_376qcOQiqGDuVlSlf00,7392
|
|
18
|
+
eqc_models-0.10.3.data/platlib/eqc_models/base/polyeval.c,sha256=OHAMclzGp8GW6JPF2cANT8tTA4Wj0n82nucfJquMkO8,438431
|
|
19
|
+
eqc_models-0.10.3.data/platlib/eqc_models/base/polyeval.cpython-310-darwin.so,sha256=EqawhkeRtBexOXXkt-k12SIN76LAlVCIW9taTWFn0GA,101136
|
|
20
|
+
eqc_models-0.10.3.data/platlib/eqc_models/base/polyeval.pyx,sha256=76Bf99Jt1_rLh5byrZxAjavE2F4_yCysirViqOBFIXw,2547
|
|
21
|
+
eqc_models-0.10.3.data/platlib/eqc_models/base/polynomial.py,sha256=FQA26ihFlwfHz9k9XP3qDM0hl5Ko4rtUxiXloj3ail4,13056
|
|
22
|
+
eqc_models-0.10.3.data/platlib/eqc_models/base/quadratic.py,sha256=BHZKniUvSq30pZgzguVasdO39BCEYue_wi5AIklPGS8,8062
|
|
23
|
+
eqc_models-0.10.3.data/platlib/eqc_models/combinatorics/__init__.py,sha256=BhzcVxwpWu2b4jIe0bmPzD5VmSyzwp0oW2q9iYx2IUs,167
|
|
24
|
+
eqc_models-0.10.3.data/platlib/eqc_models/combinatorics/setcover.py,sha256=T5hXoE9Ecw3mTHPLmifBwTzpF_4MhoCUgo2rkSOWt5s,3396
|
|
25
|
+
eqc_models-0.10.3.data/platlib/eqc_models/combinatorics/setpartition.py,sha256=ZD69kgEYSU3KWnx0b4MVCP8XSxbA_VCXOW22_Yssl_M,6254
|
|
26
|
+
eqc_models-0.10.3.data/platlib/eqc_models/graph/__init__.py,sha256=zlPE_c92wsuzz_wQLs0nxYi7tHCYxrPs-yOa9BhQAIo,162
|
|
27
|
+
eqc_models-0.10.3.data/platlib/eqc_models/graph/base.py,sha256=j48OwhorZ5jTlTysTmMiXCeiAdj6jylBREk3NxCpFLI,2072
|
|
28
|
+
eqc_models-0.10.3.data/platlib/eqc_models/graph/hypergraph.py,sha256=ABvutT0NOdIEpUF4TjUzboE4Y_J5iUZyj6-AzKr4R28,13268
|
|
29
|
+
eqc_models-0.10.3.data/platlib/eqc_models/graph/maxcut.py,sha256=o8xVsAwTa9jcpmsIoCQ5z7HSstVdraT8TENomdT519o,4132
|
|
30
|
+
eqc_models-0.10.3.data/platlib/eqc_models/graph/maxkcut.py,sha256=rEDBjto2MbuPh4c0RwTOZoVffKgcriqHNOZAIuBlclQ,4654
|
|
31
|
+
eqc_models-0.10.3.data/platlib/eqc_models/graph/partition.py,sha256=HMpRRipLp14x8pHucY-g6fU7v0PGoy1pf_KpzbanfD0,5800
|
|
32
|
+
eqc_models-0.10.3.data/platlib/eqc_models/ml/__init__.py,sha256=CLfraacr0FrD5ynxlNB6cyNy0lpbavcQT45TvkDrNvY,369
|
|
33
|
+
eqc_models-0.10.3.data/platlib/eqc_models/ml/classifierbase.py,sha256=1yXufiUGpaiBjI2evMiwfYn-Zr-SnWwCnvtREqprtJw,2184
|
|
34
|
+
eqc_models-0.10.3.data/platlib/eqc_models/ml/classifierqboost.py,sha256=5Dcpd0DjpMmlUULyZFKKWm4UuZpeMaknWKViiIjwc0U,18978
|
|
35
|
+
eqc_models-0.10.3.data/platlib/eqc_models/ml/classifierqsvm.py,sha256=b6TdwlghR84UoQpfUThwMwNF_wmkABbCqOn6T1uY2dA,6636
|
|
36
|
+
eqc_models-0.10.3.data/platlib/eqc_models/ml/clustering.py,sha256=yhh6jlgwZiQVn9h2pnYBlzVTCocK7rzsEurSQxCn5FQ,9486
|
|
37
|
+
eqc_models-0.10.3.data/platlib/eqc_models/ml/clusteringbase.py,sha256=AvQbt6jeocBAGCuAmXHKyr3wLWqYUtBDq9PbsEOSlSc,2632
|
|
38
|
+
eqc_models-0.10.3.data/platlib/eqc_models/ml/cvqboost_hamiltonian.pyx,sha256=3PMmEJ_xfmmWXGfire0t-WASnmKj6-CblufgQ2NTARo,2111
|
|
39
|
+
eqc_models-0.10.3.data/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.c,sha256=ZoKgm_uGjTewhk4W6s-x8QoFuZO0KVkxILIFh6JKsoI,1851
|
|
40
|
+
eqc_models-0.10.3.data/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.h,sha256=aOImMG5pziUnZxGpDXyWjLrvcY7ZdsczwwSQ2ay4T88,272
|
|
41
|
+
eqc_models-0.10.3.data/platlib/eqc_models/ml/decomposition.py,sha256=Nsnq0GmINpbGOszndgCHXqKdECNpiNiampBrHPU_Gjg,8943
|
|
42
|
+
eqc_models-0.10.3.data/platlib/eqc_models/ml/forecast.py,sha256=fFcBxQK9ZryfEuyvlr9HXicHoZRzLFybimYYttzhI9E,7403
|
|
43
|
+
eqc_models-0.10.3.data/platlib/eqc_models/ml/forecastbase.py,sha256=s-6nUMvtYqG07r7MmmkFVj8_QqgeGkD-HVoEEDTE2bk,3654
|
|
44
|
+
eqc_models-0.10.3.data/platlib/eqc_models/ml/regressor.py,sha256=LA1woXCnefG0wfoOxilX1kszgCUmfNcbQgs_WZ4Ai0o,5683
|
|
45
|
+
eqc_models-0.10.3.data/platlib/eqc_models/ml/regressorbase.py,sha256=H5E8-8pUji1oH5JRdS37LJQoHuKt2JU8eXCZp-ZaEM4,2109
|
|
46
|
+
eqc_models-0.10.3.data/platlib/eqc_models/ml/reservoir.py,sha256=cPRvpCaWLYTBkui35jCssHcOPQgSQZallrG6Ac9djVI,2827
|
|
47
|
+
eqc_models-0.10.3.data/platlib/eqc_models/sequence/__init__.py,sha256=VXlYufO3GYFsM00oii9Cite2WsQEF8XTwRcjLPH_Zlg,92
|
|
48
|
+
eqc_models-0.10.3.data/platlib/eqc_models/sequence/tsp.py,sha256=YM641FTyK5NkgRGxHrU1QmMkEU0gf77nEmIElTqa6Qw,7680
|
|
49
|
+
eqc_models-0.10.3.data/platlib/eqc_models/solvers/__init__.py,sha256=hTjJI4F0FNDgQlK_oRHJxLIkg6of3I1-nEqU_3RL4Gk,542
|
|
50
|
+
eqc_models-0.10.3.data/platlib/eqc_models/solvers/qciclient.py,sha256=uZrtK03oA9ozTGD--hUicmu8zoHYkuIaJ924tOtGwzU,27269
|
|
51
|
+
eqc_models-0.10.3.data/platlib/eqc_models/utilities/__init__.py,sha256=SI2U7JKmPWSiq-F1WcSyfd7l9V6nbOZv_p8quMAZaT0,340
|
|
52
|
+
eqc_models-0.10.3.data/platlib/eqc_models/utilities/fileio.py,sha256=alWPTfjGFx6Iio9HZAAWtYcLmZsBBifg6S6_YbFMQhk,1088
|
|
53
|
+
eqc_models-0.10.3.data/platlib/eqc_models/utilities/polynomial.py,sha256=blXfu7Ehz9lT4nEmIinRzJOL27_qUHSbQ57zxmwDJCA,4735
|
|
54
|
+
eqc_models-0.10.3.data/platlib/eqc_models/utilities/qplib.py,sha256=Do-MjmCFdI5HyDOAjfoz4_5lugySLMBlMAWDLUWx2OA,15796
|
|
55
|
+
eqc_models-0.10.3.dist-info/licenses/LICENSE.txt,sha256=8eh0oqsNNVR1Jk-13gkqRRSo2axtUU5kp2KzH4f9u3U,11354
|
|
56
|
+
eqc_models-0.10.3.dist-info/METADATA,sha256=FnNDJZMf48W-Xe09DRn9T4iEJjHoXJleIui-4Dy23nU,7129
|
|
57
|
+
eqc_models-0.10.3.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
58
|
+
eqc_models-0.10.3.dist-info/top_level.txt,sha256=9ZfFeKNEvkRlKWoUnfcZ9TzmTdgdsuPEnTPy11Hqf4Q,30
|
|
59
|
+
eqc_models-0.10.3.dist-info/RECORD,,
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import logging
|
|
3
|
-
from typing import (Dict, List, Tuple)
|
|
4
|
-
import numpy as np
|
|
5
|
-
from eqc_direct.client import EqcClient
|
|
6
|
-
|
|
7
|
-
log = logging.getLogger(name=__name__)
|
|
8
|
-
|
|
9
|
-
# base class
|
|
10
|
-
class EqcModel:
|
|
11
|
-
""" EqcModel subclasses must provide these properties/methods.
|
|
12
|
-
|
|
13
|
-
:decode: takes a raw solution and translates it into the original problem
|
|
14
|
-
formulation
|
|
15
|
-
:H: property which returns a Hamiltonian operator
|
|
16
|
-
:levels: property to set the number of levels in each qudit
|
|
17
|
-
:qudit_limits: maximjm value permitted for each qudit """
|
|
18
|
-
|
|
19
|
-
_levels = 100
|
|
20
|
-
_domains = None
|
|
21
|
-
_H = None
|
|
22
|
-
_machine_slacks = 0
|
|
23
|
-
|
|
24
|
-
def decode(self, solution : np.ndarray) -> np.ndarray:
|
|
25
|
-
""" Interpret the solution given the norm value and domains """
|
|
26
|
-
|
|
27
|
-
# ignore any slacks that may have been added during encoding
|
|
28
|
-
solution = solution[:self.n]
|
|
29
|
-
if self._domains is not None:
|
|
30
|
-
multipliers = self.domains / self.sum_constraint
|
|
31
|
-
else:
|
|
32
|
-
multipliers = self.sum_constraint / np.sum(solution)
|
|
33
|
-
|
|
34
|
-
return multipliers * solution
|
|
35
|
-
|
|
36
|
-
def encode(self, norm_value:float=1000) -> np.ndarray:
|
|
37
|
-
""" Encode Hamiltonian into the domain of the device """
|
|
38
|
-
|
|
39
|
-
raise NotImplementedError()
|
|
40
|
-
|
|
41
|
-
def encode_sum_constraint(self, levels):
|
|
42
|
-
new_sc = self.n * (levels-1) * self.sum_constraint / (np.sum(self.domains))
|
|
43
|
-
return new_sc
|
|
44
|
-
|
|
45
|
-
@property
|
|
46
|
-
def domains(self) -> np.array:
|
|
47
|
-
return self._domains
|
|
48
|
-
|
|
49
|
-
@domains.setter
|
|
50
|
-
def domains(self, value):
|
|
51
|
-
self._domains = value
|
|
52
|
-
|
|
53
|
-
@property
|
|
54
|
-
def n(self) -> int:
|
|
55
|
-
return int(max(self.domains.shape))
|
|
56
|
-
|
|
57
|
-
def processH(self, H : np.ndarray) -> np.ndarray:
|
|
58
|
-
""" By default, do nothing to H """
|
|
59
|
-
|
|
60
|
-
return H
|
|
61
|
-
|
|
62
|
-
@property
|
|
63
|
-
def H(self) -> Dict[str, np.ndarray]:
|
|
64
|
-
""" Matrix of a quadratic operator with the first column containing
|
|
65
|
-
the linear terms and the remaining columns containing a symmetric
|
|
66
|
-
quadratic matrix"""
|
|
67
|
-
return self._H
|
|
68
|
-
|
|
69
|
-
@H.setter
|
|
70
|
-
def H(self, value : Dict[str, np.ndarray]):
|
|
71
|
-
""" The H setter ensures that matrices order 2 and above are symmetric """
|
|
72
|
-
|
|
73
|
-
H = self.processH(value)
|
|
74
|
-
self._H = H
|
|
75
|
-
|
|
76
|
-
@property
|
|
77
|
-
def sparse(self) -> Tuple[np.ndarray, np.ndarray]:
|
|
78
|
-
H = self.H
|
|
79
|
-
coeff = []
|
|
80
|
-
idx = []
|
|
81
|
-
poly_orders = {"C": 1, "J": 2, "T": 3, "Q": 4, "P": 5}
|
|
82
|
-
key_len = max([poly_orders[k] for k, v in H.items() if v is not None])
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
@property
|
|
86
|
-
def machine_slacks(self):
|
|
87
|
-
""" Number of slack qudits to add to the model """
|
|
88
|
-
return self._machine_slacks
|
|
89
|
-
|
|
90
|
-
@machine_slacks.setter
|
|
91
|
-
def machine_slacks(self, value:int):
|
|
92
|
-
assert int(value) == value, "value not integer"
|
|
93
|
-
self._machine_slacks = value
|
|
94
|
-
|
|
95
|
-
class ModelSolver:
|
|
96
|
-
""" Provide a common interface for solver implementations.
|
|
97
|
-
Store a model, implement a solve method."""
|
|
98
|
-
|
|
99
|
-
def __init__(self, model : EqcModel, levels : int = 200):
|
|
100
|
-
self.model = model
|
|
101
|
-
self._levels = levels
|
|
102
|
-
|
|
103
|
-
def solve(self, *args, **kwargs) -> Dict:
|
|
104
|
-
raise NotImplementedError()
|
|
105
|
-
|
|
106
|
-
@property
|
|
107
|
-
def levels(self) -> int:
|
|
108
|
-
""" This integer value indicates the number of distinct
|
|
109
|
-
states each qudit can represent. These levels are separated
|
|
110
|
-
by some constant value with the first level taking the value 0. """
|
|
111
|
-
return self._levels
|
|
112
|
-
|
|
113
|
-
@levels.setter
|
|
114
|
-
def levels(self, value : int):
|
|
115
|
-
self._levels = value
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# (C) Quantum Computing Inc., 2024.
|
|
2
|
-
import numpy as np
|
|
3
|
-
import networkx as nx
|
|
4
|
-
from .graphs import GraphModel
|
|
5
|
-
|
|
6
|
-
class CommunityDetectionModel(GraphModel):
|
|
7
|
-
"""
|
|
8
|
-
This model is the generic n-community model, which requires enforcing
|
|
9
|
-
membership to a single community
|
|
10
|
-
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
def __init__(self, G : nx.Graph, num_communities : int):
|
|
14
|
-
super(CommunityDetectionModel, self).__init__(G)
|
|
15
|
-
self.cnum_communities = num_communities
|
|
16
|
-
|
|
17
|
-
def build(self):
|
|
18
|
-
# num_nodes = len(self.G.nodes)
|
|
19
|
-
# num_variables = num_nodes * self.num_communities
|
|
20
|
-
# lhs = np.zeros((num_nodes, num_variables), dtype=np.int32)
|
|
21
|
-
# rhs = np.ones((num_nodes, 1), dtype=np.int32)
|
|
22
|
-
# for i in range(num_nodes):
|
|
23
|
-
# lhs[i, 3*i:3*(i+1)] = 1
|
|
24
|
-
# self.constraints = lhs, rhs
|
|
25
|
-
raise NotImplementedError("Community Detection is not implemented yet")
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
from typing import Dict
|
|
2
|
-
import logging
|
|
3
|
-
import numpy as np
|
|
4
|
-
from eqc_direct.client import EqcClient
|
|
5
|
-
from .base import ModelSolver
|
|
6
|
-
|
|
7
|
-
log = logging.getLogger(name=__name__)
|
|
8
|
-
|
|
9
|
-
class EqcDirectMixin:
|
|
10
|
-
|
|
11
|
-
ip_addr = None
|
|
12
|
-
port = None
|
|
13
|
-
|
|
14
|
-
def connect(self, ip_addr : str, port : str):
|
|
15
|
-
""" Explicitly set device address, if environment is configured with the connection, this call is not required """
|
|
16
|
-
self.ip_addr = ip_addr
|
|
17
|
-
self.port = port
|
|
18
|
-
|
|
19
|
-
@property
|
|
20
|
-
def client(self):
|
|
21
|
-
|
|
22
|
-
params = {}
|
|
23
|
-
if self.ip_addr is not None:
|
|
24
|
-
params["ip_address"] = self.ip_addr
|
|
25
|
-
if self.port is not None:
|
|
26
|
-
params["port"] = self.port
|
|
27
|
-
return EqcClient(**params)
|
|
28
|
-
|
|
29
|
-
class EqcDirectSolver(ModelSolver, EqcDirectMixin):
|
|
30
|
-
|
|
31
|
-
def solve(self, relaxation_schedule:int=2, precision : float = 1.0) -> Dict:
|
|
32
|
-
model = self.model
|
|
33
|
-
poly_coefficients, poly_indices = model.sparse
|
|
34
|
-
scval = model.encode_sum_constraint(self.levels)
|
|
35
|
-
|
|
36
|
-
client = self.client
|
|
37
|
-
lock_id, start_ts, end_ts = client.wait_for_lock()
|
|
38
|
-
log.debug("Got device lock id %s. Wait time %f", lock_id, end_ts - start_ts)
|
|
39
|
-
resp = None
|
|
40
|
-
try:
|
|
41
|
-
log.debug("Calling device with parameters relaxation_schedule %d sum_constraint %s lock_id %s solution_precision %f",
|
|
42
|
-
relaxation_schedule, scval, lock_id, precision)
|
|
43
|
-
resp = client.process_job(poly_coefficients=poly_coefficients,
|
|
44
|
-
poly_indices=poly_indices,
|
|
45
|
-
relaxation_schedule=relaxation_schedule,
|
|
46
|
-
sum_constraint = scval,
|
|
47
|
-
lock_id = lock_id,
|
|
48
|
-
solution_precision=precision)
|
|
49
|
-
log.debug("Received response with status %s", resp["err_desc"])
|
|
50
|
-
log.debug("Runtime %f resulting in energy %f", resp["runtime"], resp["energy"])
|
|
51
|
-
log.debug("Distillation runtime %s resulting in energy %f", resp["distilled_runtime"], resp["distilled_energy"])
|
|
52
|
-
finally:
|
|
53
|
-
client.release_lock(lock_id=lock_id)
|
|
54
|
-
if resp is not None:
|
|
55
|
-
solution = resp["solution"]
|
|
56
|
-
energy = resp["energy"]
|
|
57
|
-
runtime = resp["runtime"]
|
|
58
|
-
dirac3_sol = np.array(solution)
|
|
59
|
-
else:
|
|
60
|
-
raise RuntimeError("FAILED TO GET RESPONSE")
|
|
61
|
-
return resp
|