eqc-models 0.10.1__py3-none-any.whl → 0.11.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 (72) hide show
  1. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/__init__.py +2 -1
  2. eqc_models-0.11.0.data/platlib/eqc_models/assignment/setpartition.py +4 -0
  3. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/base/__init__.py +3 -1
  4. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/base/base.py +44 -4
  5. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/base/polyeval.c +163 -163
  6. eqc_models-0.11.0.data/platlib/eqc_models/base/polyeval.cpython-310-darwin.so +0 -0
  7. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/base/polynomial.py +7 -3
  8. eqc_models-0.11.0.data/platlib/eqc_models/base/results.py +94 -0
  9. eqc_models-0.11.0.data/platlib/eqc_models/combinatorics/__init__.py +6 -0
  10. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/combinatorics/setcover.py +34 -17
  11. {eqc_models-0.10.1.data/platlib/eqc_models/assignment → eqc_models-0.11.0.data/platlib/eqc_models/combinatorics}/setpartition.py +2 -0
  12. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/graph/maxkcut.py +26 -68
  13. eqc_models-0.11.0.data/platlib/eqc_models/sequence/scheduling.py +29 -0
  14. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/solvers/qciclient.py +11 -2
  15. {eqc_models-0.10.1.dist-info → eqc_models-0.11.0.dist-info}/METADATA +3 -2
  16. eqc_models-0.11.0.dist-info/RECORD +61 -0
  17. {eqc_models-0.10.1.dist-info → eqc_models-0.11.0.dist-info}/WHEEL +1 -1
  18. eqc_models-0.10.1.data/platlib/eqc_models/base/polyeval.cpython-310-darwin.so +0 -0
  19. eqc_models-0.10.1.data/platlib/eqc_models/base.py +0 -115
  20. eqc_models-0.10.1.data/platlib/eqc_models/combinatorics/__init__.py +0 -5
  21. eqc_models-0.10.1.data/platlib/eqc_models/communitydetection.py +0 -25
  22. eqc_models-0.10.1.data/platlib/eqc_models/eqcdirectsolver.py +0 -61
  23. eqc_models-0.10.1.data/platlib/eqc_models/graphs.py +0 -28
  24. eqc_models-0.10.1.data/platlib/eqc_models/maxcut.py +0 -113
  25. eqc_models-0.10.1.data/platlib/eqc_models/maxkcut.py +0 -185
  26. eqc_models-0.10.1.data/platlib/eqc_models/quadraticmodel.py +0 -131
  27. eqc_models-0.10.1.data/platlib/eqc_models/solvers/eqcdirect.py +0 -160
  28. eqc_models-0.10.1.dist-info/RECORD +0 -66
  29. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/compile_extensions.py +0 -0
  30. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/algorithms/__init__.py +0 -0
  31. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/algorithms/base.py +0 -0
  32. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/algorithms/penaltymultiplier.py +0 -0
  33. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/allocation/__init__.py +0 -0
  34. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/allocation/allocation.py +0 -0
  35. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/allocation/portbase.py +0 -0
  36. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/allocation/portmomentum.py +0 -0
  37. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/assignment/__init__.py +0 -0
  38. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/assignment/qap.py +0 -0
  39. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/base/constraints.py +0 -0
  40. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/base/operators.py +0 -0
  41. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/base/polyeval.pyx +0 -0
  42. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/base/quadratic.py +0 -0
  43. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/decoding.py +0 -0
  44. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/graph/__init__.py +0 -0
  45. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/graph/base.py +0 -0
  46. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/graph/hypergraph.py +0 -0
  47. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/graph/maxcut.py +0 -0
  48. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/graph/partition.py +0 -0
  49. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/ml/__init__.py +0 -0
  50. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/ml/classifierbase.py +0 -0
  51. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/ml/classifierqboost.py +0 -0
  52. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/ml/classifierqsvm.py +0 -0
  53. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/ml/clustering.py +0 -0
  54. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/ml/clusteringbase.py +0 -0
  55. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/ml/cvqboost_hamiltonian.pyx +0 -0
  56. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.c +0 -0
  57. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.h +0 -0
  58. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/ml/decomposition.py +0 -0
  59. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/ml/forecast.py +0 -0
  60. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/ml/forecastbase.py +0 -0
  61. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/ml/regressor.py +0 -0
  62. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/ml/regressorbase.py +0 -0
  63. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/ml/reservoir.py +0 -0
  64. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/sequence/__init__.py +0 -0
  65. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/sequence/tsp.py +0 -0
  66. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/solvers/__init__.py +0 -0
  67. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/utilities/__init__.py +0 -0
  68. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/utilities/fileio.py +0 -0
  69. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/utilities/polynomial.py +0 -0
  70. {eqc_models-0.10.1.data → eqc_models-0.11.0.data}/platlib/eqc_models/utilities/qplib.py +0 -0
  71. {eqc_models-0.10.1.dist-info → eqc_models-0.11.0.dist-info/licenses}/LICENSE.txt +0 -0
  72. {eqc_models-0.10.1.dist-info → eqc_models-0.11.0.dist-info}/top_level.txt +0 -0
@@ -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(self.polynomial.indices[i]) == 2 for i in range(len(self.polynomial.indices))]):
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(self.polynomial.coefficients,
125
- self.polynomial.indices, self.n)
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
  """
@@ -0,0 +1,94 @@
1
+ import dataclasses
2
+ import warnings
3
+ import numpy as np
4
+
5
+ @dataclasses.dataclass
6
+ class SolutionResults:
7
+ """
8
+ The class is meant to provide a uniform interface to results, no matter
9
+ the method of running the job.
10
+
11
+ """
12
+
13
+ solutions : np.ndarray
14
+ energies : np.ndarray
15
+ counts : np.array
16
+ objectives : np.ndarray
17
+ run_time : np.ndarray
18
+ preprocessing_time : np.ndarray
19
+ postprocessing_time : np.ndarray
20
+ penalties : np.ndarray = None
21
+ device : str = None
22
+ time_units : str = "ns"
23
+
24
+ @property
25
+ def device_time(self):
26
+ pre = self.preprocessing_time
27
+ runtime = np.sum(self.run_time)
28
+ post = np.sum(self.postprocessing_time)
29
+ return pre + runtime + post
30
+
31
+ @property
32
+ def total_samples(self):
33
+ return np.sum(self.counts)
34
+
35
+ @property
36
+ def best_energy(self):
37
+ return np.min(self.energies)
38
+
39
+ @classmethod
40
+ def determine_device_type(cls, device_config):
41
+ """
42
+ Use the device config object from a cloud response
43
+ to get the device info. It will have a device and job type
44
+ identifiers in it.
45
+
46
+ """
47
+ devices = [k for k in device_config.keys()]
48
+ # only one device type is supported at a time
49
+ return devices[0]
50
+
51
+ @classmethod
52
+ def from_cloud_response(cls, model, response, solver):
53
+ """ Fill in the details from the cloud """
54
+
55
+ solutions = np.array(response["results"]["solutions"])
56
+ energies = np.array(response["results"]["energies"])
57
+ if hasattr(model, "evaluateObjective"):
58
+ objectives = np.zeros((solutions.shape[0],), dtype=np.float32)
59
+ for i in range(solutions.shape[0]):
60
+ try:
61
+ objective = model.evaluateObjective(solutions[i])
62
+ except NotImplementedError:
63
+ warnings.warn(f"Cannot set objective value in results for {model.__class__}")
64
+ objectives = None
65
+ break
66
+ objectives[i] = objective
67
+ else:
68
+ objectives = None
69
+ if hasattr(model, "evaluatePenalties"):
70
+ penalties = np.zeros((solutions.shape[0],), dtype=np.float32)
71
+ for i in range(solutions.shape[0]):
72
+ penalties[i] = model.evaluatePenalty(solution[i]) + model.offset
73
+ else:
74
+ penalties = None
75
+ counts = np.array(response["results"]["counts"])
76
+ # interrogate to determine the device type
77
+ try:
78
+ device_type = cls.determine_device_type(response["job_info"]["job_submission"]["device_config"])
79
+ except KeyError:
80
+ print(response.keys())
81
+ raise
82
+ job_id = response["job_info"]["job_id"]
83
+ metrics = solver.client.get_job_metrics(job_id=job_id)
84
+ metrics = metrics["job_metrics"]
85
+ time_ns = metrics["time_ns"]
86
+ device = time_ns["device"][device_type]
87
+ runtime = device["samples"]["runtime"]
88
+ post = device["samples"]["postprocessing_time"]
89
+ pre = device["samples"]["preprocessing_time"]
90
+ results = SolutionResults(solutions, energies, counts, objectives,
91
+ runtime, pre, post, penalties=penalties,
92
+ device=device_type, time_units="ns")
93
+
94
+ return results
@@ -0,0 +1,6 @@
1
+ # (C) Quantum Computing Inc., 2024.
2
+
3
+ from .setcover import SetCoverModel
4
+ from .setpartition import SetPartitionModel
5
+
6
+ __all__ = ["SetCoverModel", "SetPartitionModel"]
@@ -41,41 +41,57 @@ class SetCoverModel(ConstrainedQuadraticModel):
41
41
  >>> X = [set(['A', 'B']), set(['B', 'C']), set(['C'])]
42
42
  >>> weights = [2, 2, 1]
43
43
  >>> model = SetCoverModel(X, weights)
44
- >>> model.penalty_multiplier = 2
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]])
45
50
  >>> from eqc_models.solvers import Dirac3IntegerCloudSolver
46
51
  >>> solver = Dirac3IntegerCloudSolver()
47
52
  >>> response = solver.solve(model, relaxation_schedule=1, num_samples=5) #doctest: +ELLIPSIS
48
53
  20...
49
54
  >>> solutions = response["results"]["solutions"]
50
55
  >>> solutions[0]
51
- [1, 0, 1, 0, 0, 0]
52
- >>> model.decode(solutions[0])
53
- [{'B', 'A'}, {'C'}]
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
54
61
 
55
62
  """
56
63
 
57
64
  def __init__(self, subsets, weights):
58
65
  # ensure that X is ordered
59
- self.X = X = list(subsets)
60
- self.S = S = set()
66
+ self.S = S = list(subsets)
67
+ self.universal_set = U = set()
61
68
 
62
69
  for x in subsets:
63
- S = S.union(x)
70
+ U.update(x)
64
71
  # elements is sorted to maintain consistent output
65
- elements = [a for a in S]
72
+ elements = [a for a in U]
66
73
  elements.sort()
67
74
  # constraints
68
75
  A = []
69
76
  b = []
70
- variables = [f'x_{i}' for i in range(len(X))]
77
+ variables = [f'x_{i}' for i in range(len(S))]
71
78
  pos = 0
79
+ num_slacks = 0
80
+ slack_ub = []
72
81
  for a in elements:
73
- variables.append(f"s_{pos}")
74
- constraint = [1 if a in X[i] else 0 for i in range(len(X))]
75
- slacks = [0 for i in range(len(S))]
76
- slacks[pos] = -1
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
77
94
  A.append(constraint + slacks)
78
- pos += 1
79
95
  b.append(1)
80
96
  n = len(variables)
81
97
  J = np.zeros((n, n))
@@ -84,11 +100,12 @@ class SetCoverModel(ConstrainedQuadraticModel):
84
100
  # call the superclass constructor with the objective and constraints
85
101
  super(SetCoverModel, self).__init__(h, J, np.array(A), np.array(b))
86
102
  # set upper bound on the variables to be 1 for x_i and the length of X minus 1 for the slacks
87
- self.upper_bound = np.array([1 for i in range(len(weights))] + [len(X)-1 for i in range(n-len(weights))])
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)
88
105
 
89
106
  def decode(self, solution) -> List:
90
107
  xbar = []
91
- for i in range(len(self.X)):
108
+ for i in range(len(self.S)):
92
109
  if solution[i] > 0.5:
93
- xbar.append(self.X[i])
110
+ xbar.append(self.S[i])
94
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
- class MaxKCutModel(NodeModel):
8
+ class MaxKCutModel(ConstrainedQuadraticModel):
9
+ _objective = None
8
10
 
9
11
  def __init__(self, G : nx.Graph, k : int):
10
- super(MaxKCutModel, self).__init__(G)
12
+ self.G = G
11
13
  self.k = k
12
- self.lhs = None
13
- self.rhs = None
14
- self._objective = None
15
- self._J = None
16
- self._C = None
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
- for i, u in enumerate(self.variables):
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
- n = len(self.variables)
43
+ G = self.G
39
44
  partition_num = {}
40
- for i, u in enumerate(self.variables):
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 _build_objective(self):
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
- self._objective = (np.zeros((n, 1)), objective)
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
- self.lhs = A
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
- if self.rhs is None:
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
- self._objective = (np.zeros((n, 1)), objective)
135
+ return (np.zeros((n, 1)), objective)
178
136
 
179
137
  def getCutSize(self, partition):
180
138
  cut_size = 0
@@ -0,0 +1,29 @@
1
+ import numpy as np
2
+ from eqc_models.base.quadratic import ConstrainedQuadraticModel
3
+ from eqc_models.base.constraints import InequalitiesMixin
4
+
5
+ class CrewSchedulingModel(ConstrainedQuadraticModel):
6
+ """
7
+ Crew scheduling model
8
+
9
+ Parameters
10
+ ------------
11
+
12
+ crews : List
13
+ tasks : List
14
+
15
+ >>> crews = [{"name": "Maintenance Crew 1", "skills": ["A", "F"]},
16
+ ... {"name": "Baggage Crew 1", "skills": ["B"]},
17
+ ... {"name": "Maintenance Crew 2", "skills": ["A", "F"]}]
18
+ >>> tasks = [{"name": "Refuel", "skill_need": "F"},
19
+ ... {"name": "Baggage", "skill_need": "B"}]
20
+
21
+ """
22
+
23
+ def __init__(self, crews, tasks):
24
+ self.crews = crews
25
+ self.tasks = tasks
26
+
27
+ def decode(self, solution) -> np.ndarray:
28
+ """ Translate the solution into a list of tasks for each crew """
29
+
@@ -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 = 1
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 = 0
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.2
1
+ Metadata-Version: 2.4
2
2
  Name: eqc-models
3
- Version: 0.10.1
3
+ Version: 0.11.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
@@ -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,61 @@
1
+ eqc_models-0.11.0.data/platlib/compile_extensions.py,sha256=ivFZ87WFzBITU7IwK_72C41MDNMortJIF8tKevm2aW4,1946
2
+ eqc_models-0.11.0.data/platlib/eqc_models/__init__.py,sha256=WPUijJz2-4UZU-ZTqBofDc-Yaah24geHdmF16SkwIj4,683
3
+ eqc_models-0.11.0.data/platlib/eqc_models/decoding.py,sha256=G3JgbIFzvZ3DIKW0kZ1JeTMIZmrc8hy9kzdbX2Xv5Og,637
4
+ eqc_models-0.11.0.data/platlib/eqc_models/algorithms/__init__.py,sha256=lzQoMMSs2QTqp5suEYNvcQaSEN16d0LwIsZ1mRstumU,135
5
+ eqc_models-0.11.0.data/platlib/eqc_models/algorithms/base.py,sha256=qfQQTwuVyewn7Qpg1_SVoD_7TsdA8vdwSKGqOeZSmNI,204
6
+ eqc_models-0.11.0.data/platlib/eqc_models/algorithms/penaltymultiplier.py,sha256=SndGxCZDS3JTaxFOPJpTBumFdIKcB0dKwSHwfl_BI6o,7845
7
+ eqc_models-0.11.0.data/platlib/eqc_models/allocation/__init__.py,sha256=op_udrapTlWrakTuQId3M0ggo-Y1w4nGJLPcYKOQ-8I,239
8
+ eqc_models-0.11.0.data/platlib/eqc_models/allocation/allocation.py,sha256=PAQn4M75Zegeoy0i6r3hycWs4TKeRglHk05TvwZOoLk,15506
9
+ eqc_models-0.11.0.data/platlib/eqc_models/allocation/portbase.py,sha256=BTnYYduHydPbrE2yQr_Sgv3XJACH_GpIJstuMrfGqCU,3269
10
+ eqc_models-0.11.0.data/platlib/eqc_models/allocation/portmomentum.py,sha256=oMod63rNDC-01dLZjmhUb24SN3_GVgfc6CItgQL_obI,3756
11
+ eqc_models-0.11.0.data/platlib/eqc_models/assignment/__init__.py,sha256=CX_QYl8P1meajV8gcVs6hm07VhoLVe8uu436t7-1XQo,86
12
+ eqc_models-0.11.0.data/platlib/eqc_models/assignment/qap.py,sha256=WMiQQmTORsgi2w7kbmMA1xo-93dESLECWqYTF-zkmTs,2963
13
+ eqc_models-0.11.0.data/platlib/eqc_models/assignment/setpartition.py,sha256=5SQxF_ZlQk4ubWf5_3TgL83k01hAakUP-5AydlD-BvE,161
14
+ eqc_models-0.11.0.data/platlib/eqc_models/base/__init__.py,sha256=wKBppDk1lBiDvGOFnNpzu4lh7n4dQiyd_x3lNQJumTw,2952
15
+ eqc_models-0.11.0.data/platlib/eqc_models/base/base.py,sha256=tL6z0MW4ffMKWlozZ0CH4soTiKxSlMXqyVDctaA110U,6405
16
+ eqc_models-0.11.0.data/platlib/eqc_models/base/constraints.py,sha256=KMPyCdt_8GMWLnVEdpzw1T1WqXm2f7Lh629ClUH7XDY,8271
17
+ eqc_models-0.11.0.data/platlib/eqc_models/base/operators.py,sha256=9nCeN6fRP-_YBfs-Gm57D-O_376qcOQiqGDuVlSlf00,7392
18
+ eqc_models-0.11.0.data/platlib/eqc_models/base/polyeval.c,sha256=xyZgxdE5DbBJP3Q8ol7t5651V7bjVZNKH24HAeADeNk,438431
19
+ eqc_models-0.11.0.data/platlib/eqc_models/base/polyeval.cpython-310-darwin.so,sha256=gS8RuuiASVDgHRiexrTgQiydL-CtTAMUts7jPOAPpJ4,108672
20
+ eqc_models-0.11.0.data/platlib/eqc_models/base/polyeval.pyx,sha256=76Bf99Jt1_rLh5byrZxAjavE2F4_yCysirViqOBFIXw,2547
21
+ eqc_models-0.11.0.data/platlib/eqc_models/base/polynomial.py,sha256=FQA26ihFlwfHz9k9XP3qDM0hl5Ko4rtUxiXloj3ail4,13056
22
+ eqc_models-0.11.0.data/platlib/eqc_models/base/quadratic.py,sha256=BHZKniUvSq30pZgzguVasdO39BCEYue_wi5AIklPGS8,8062
23
+ eqc_models-0.11.0.data/platlib/eqc_models/base/results.py,sha256=SPTDdlA2BOQjoaNvp7UGB1v5Veys8AGjQ3VDC1NpEQY,3301
24
+ eqc_models-0.11.0.data/platlib/eqc_models/combinatorics/__init__.py,sha256=BhzcVxwpWu2b4jIe0bmPzD5VmSyzwp0oW2q9iYx2IUs,167
25
+ eqc_models-0.11.0.data/platlib/eqc_models/combinatorics/setcover.py,sha256=T5hXoE9Ecw3mTHPLmifBwTzpF_4MhoCUgo2rkSOWt5s,3396
26
+ eqc_models-0.11.0.data/platlib/eqc_models/combinatorics/setpartition.py,sha256=ZD69kgEYSU3KWnx0b4MVCP8XSxbA_VCXOW22_Yssl_M,6254
27
+ eqc_models-0.11.0.data/platlib/eqc_models/graph/__init__.py,sha256=zlPE_c92wsuzz_wQLs0nxYi7tHCYxrPs-yOa9BhQAIo,162
28
+ eqc_models-0.11.0.data/platlib/eqc_models/graph/base.py,sha256=j48OwhorZ5jTlTysTmMiXCeiAdj6jylBREk3NxCpFLI,2072
29
+ eqc_models-0.11.0.data/platlib/eqc_models/graph/hypergraph.py,sha256=ABvutT0NOdIEpUF4TjUzboE4Y_J5iUZyj6-AzKr4R28,13268
30
+ eqc_models-0.11.0.data/platlib/eqc_models/graph/maxcut.py,sha256=o8xVsAwTa9jcpmsIoCQ5z7HSstVdraT8TENomdT519o,4132
31
+ eqc_models-0.11.0.data/platlib/eqc_models/graph/maxkcut.py,sha256=rEDBjto2MbuPh4c0RwTOZoVffKgcriqHNOZAIuBlclQ,4654
32
+ eqc_models-0.11.0.data/platlib/eqc_models/graph/partition.py,sha256=HMpRRipLp14x8pHucY-g6fU7v0PGoy1pf_KpzbanfD0,5800
33
+ eqc_models-0.11.0.data/platlib/eqc_models/ml/__init__.py,sha256=CLfraacr0FrD5ynxlNB6cyNy0lpbavcQT45TvkDrNvY,369
34
+ eqc_models-0.11.0.data/platlib/eqc_models/ml/classifierbase.py,sha256=1yXufiUGpaiBjI2evMiwfYn-Zr-SnWwCnvtREqprtJw,2184
35
+ eqc_models-0.11.0.data/platlib/eqc_models/ml/classifierqboost.py,sha256=5Dcpd0DjpMmlUULyZFKKWm4UuZpeMaknWKViiIjwc0U,18978
36
+ eqc_models-0.11.0.data/platlib/eqc_models/ml/classifierqsvm.py,sha256=b6TdwlghR84UoQpfUThwMwNF_wmkABbCqOn6T1uY2dA,6636
37
+ eqc_models-0.11.0.data/platlib/eqc_models/ml/clustering.py,sha256=yhh6jlgwZiQVn9h2pnYBlzVTCocK7rzsEurSQxCn5FQ,9486
38
+ eqc_models-0.11.0.data/platlib/eqc_models/ml/clusteringbase.py,sha256=AvQbt6jeocBAGCuAmXHKyr3wLWqYUtBDq9PbsEOSlSc,2632
39
+ eqc_models-0.11.0.data/platlib/eqc_models/ml/cvqboost_hamiltonian.pyx,sha256=3PMmEJ_xfmmWXGfire0t-WASnmKj6-CblufgQ2NTARo,2111
40
+ eqc_models-0.11.0.data/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.c,sha256=ZoKgm_uGjTewhk4W6s-x8QoFuZO0KVkxILIFh6JKsoI,1851
41
+ eqc_models-0.11.0.data/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.h,sha256=aOImMG5pziUnZxGpDXyWjLrvcY7ZdsczwwSQ2ay4T88,272
42
+ eqc_models-0.11.0.data/platlib/eqc_models/ml/decomposition.py,sha256=Nsnq0GmINpbGOszndgCHXqKdECNpiNiampBrHPU_Gjg,8943
43
+ eqc_models-0.11.0.data/platlib/eqc_models/ml/forecast.py,sha256=fFcBxQK9ZryfEuyvlr9HXicHoZRzLFybimYYttzhI9E,7403
44
+ eqc_models-0.11.0.data/platlib/eqc_models/ml/forecastbase.py,sha256=s-6nUMvtYqG07r7MmmkFVj8_QqgeGkD-HVoEEDTE2bk,3654
45
+ eqc_models-0.11.0.data/platlib/eqc_models/ml/regressor.py,sha256=LA1woXCnefG0wfoOxilX1kszgCUmfNcbQgs_WZ4Ai0o,5683
46
+ eqc_models-0.11.0.data/platlib/eqc_models/ml/regressorbase.py,sha256=H5E8-8pUji1oH5JRdS37LJQoHuKt2JU8eXCZp-ZaEM4,2109
47
+ eqc_models-0.11.0.data/platlib/eqc_models/ml/reservoir.py,sha256=cPRvpCaWLYTBkui35jCssHcOPQgSQZallrG6Ac9djVI,2827
48
+ eqc_models-0.11.0.data/platlib/eqc_models/sequence/__init__.py,sha256=VXlYufO3GYFsM00oii9Cite2WsQEF8XTwRcjLPH_Zlg,92
49
+ eqc_models-0.11.0.data/platlib/eqc_models/sequence/scheduling.py,sha256=9gSD-L_n18NrE8K6CYTaIYRJ1JYI1ILhdEsk6xtsa68,841
50
+ eqc_models-0.11.0.data/platlib/eqc_models/sequence/tsp.py,sha256=YM641FTyK5NkgRGxHrU1QmMkEU0gf77nEmIElTqa6Qw,7680
51
+ eqc_models-0.11.0.data/platlib/eqc_models/solvers/__init__.py,sha256=hTjJI4F0FNDgQlK_oRHJxLIkg6of3I1-nEqU_3RL4Gk,542
52
+ eqc_models-0.11.0.data/platlib/eqc_models/solvers/qciclient.py,sha256=uZrtK03oA9ozTGD--hUicmu8zoHYkuIaJ924tOtGwzU,27269
53
+ eqc_models-0.11.0.data/platlib/eqc_models/utilities/__init__.py,sha256=SI2U7JKmPWSiq-F1WcSyfd7l9V6nbOZv_p8quMAZaT0,340
54
+ eqc_models-0.11.0.data/platlib/eqc_models/utilities/fileio.py,sha256=alWPTfjGFx6Iio9HZAAWtYcLmZsBBifg6S6_YbFMQhk,1088
55
+ eqc_models-0.11.0.data/platlib/eqc_models/utilities/polynomial.py,sha256=blXfu7Ehz9lT4nEmIinRzJOL27_qUHSbQ57zxmwDJCA,4735
56
+ eqc_models-0.11.0.data/platlib/eqc_models/utilities/qplib.py,sha256=Do-MjmCFdI5HyDOAjfoz4_5lugySLMBlMAWDLUWx2OA,15796
57
+ eqc_models-0.11.0.dist-info/licenses/LICENSE.txt,sha256=8eh0oqsNNVR1Jk-13gkqRRSo2axtUU5kp2KzH4f9u3U,11354
58
+ eqc_models-0.11.0.dist-info/METADATA,sha256=6Ixla2-iQUpemI_tFaSn1vAeSR5c60n0XJX0kiFbk3I,7129
59
+ eqc_models-0.11.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
60
+ eqc_models-0.11.0.dist-info/top_level.txt,sha256=9ZfFeKNEvkRlKWoUnfcZ9TzmTdgdsuPEnTPy11Hqf4Q,30
61
+ eqc_models-0.11.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.0)
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5