eqc-models 0.11.1__py3-none-any.whl → 0.13.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.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/base/base.py +11 -0
  2. eqc_models-0.13.0.data/platlib/eqc_models/base/binaries.py +33 -0
  3. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/base/constraints.py +39 -0
  4. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/base/polyeval.c +4375 -3426
  5. eqc_models-0.13.0.data/platlib/eqc_models/base/polyeval.cpython-310-darwin.so +0 -0
  6. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/base/polynomial.py +21 -2
  7. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/base/quadratic.py +2 -2
  8. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/base/results.py +81 -1
  9. eqc_models-0.13.0.data/platlib/eqc_models/graph/__init__.py +11 -0
  10. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/graph/base.py +8 -4
  11. eqc_models-0.13.0.data/platlib/eqc_models/graph/rcshortestpath.py +81 -0
  12. eqc_models-0.13.0.data/platlib/eqc_models/graph/shortestpath.py +190 -0
  13. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/ml/classifierbase.py +30 -5
  14. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/ml/classifierqboost.py +14 -1
  15. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/ml/classifierqsvm.py +28 -0
  16. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/ml/clustering.py +5 -5
  17. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/ml/clusteringbase.py +1 -2
  18. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/ml/decomposition.py +0 -1
  19. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/ml/regressorbase.py +0 -1
  20. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/process/base.py +6 -1
  21. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/process/mpc.py +1 -1
  22. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/solvers/__init__.py +10 -6
  23. eqc_models-0.13.0.data/platlib/eqc_models/solvers/eqcdirect.py +76 -0
  24. eqc_models-0.13.0.data/platlib/eqc_models/solvers/mip.py +115 -0
  25. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/solvers/qciclient.py +11 -22
  26. eqc_models-0.13.0.data/platlib/eqc_models/solvers/responselog.py +47 -0
  27. {eqc_models-0.11.1.dist-info → eqc_models-0.13.0.dist-info}/METADATA +7 -9
  28. eqc_models-0.13.0.dist-info/RECORD +69 -0
  29. {eqc_models-0.11.1.dist-info → eqc_models-0.13.0.dist-info}/WHEEL +1 -1
  30. eqc_models-0.11.1.data/platlib/eqc_models/base/polyeval.cpython-310-darwin.so +0 -0
  31. eqc_models-0.11.1.data/platlib/eqc_models/graph/__init__.py +0 -6
  32. eqc_models-0.11.1.dist-info/RECORD +0 -63
  33. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/compile_extensions.py +0 -0
  34. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/__init__.py +0 -0
  35. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/algorithms/__init__.py +0 -0
  36. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/algorithms/base.py +0 -0
  37. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/algorithms/penaltymultiplier.py +0 -0
  38. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/allocation/__init__.py +0 -0
  39. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/allocation/allocation.py +0 -0
  40. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/allocation/portbase.py +0 -0
  41. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/allocation/portmomentum.py +0 -0
  42. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/assignment/__init__.py +0 -0
  43. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/assignment/qap.py +0 -0
  44. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/assignment/resource.py +0 -0
  45. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/assignment/setpartition.py +0 -0
  46. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/base/__init__.py +0 -0
  47. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/base/operators.py +0 -0
  48. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/base/polyeval.pyx +0 -0
  49. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/combinatorics/__init__.py +0 -0
  50. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/combinatorics/setcover.py +0 -0
  51. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/combinatorics/setpartition.py +0 -0
  52. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/decoding.py +0 -0
  53. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/graph/hypergraph.py +0 -0
  54. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/graph/maxcut.py +0 -0
  55. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/graph/maxkcut.py +0 -0
  56. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/graph/partition.py +0 -0
  57. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/ml/__init__.py +0 -0
  58. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/ml/cvqboost_hamiltonian.pyx +0 -0
  59. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.c +0 -0
  60. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.h +0 -0
  61. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/ml/forecast.py +0 -0
  62. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/ml/forecastbase.py +0 -0
  63. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/ml/regressor.py +0 -0
  64. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/ml/reservoir.py +0 -0
  65. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/sequence/__init__.py +0 -0
  66. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/sequence/tsp.py +0 -0
  67. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/utilities/__init__.py +0 -0
  68. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/utilities/fileio.py +0 -0
  69. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/utilities/polynomial.py +0 -0
  70. {eqc_models-0.11.1.data → eqc_models-0.13.0.data}/platlib/eqc_models/utilities/qplib.py +0 -0
  71. {eqc_models-0.11.1.dist-info → eqc_models-0.13.0.dist-info}/licenses/LICENSE.txt +0 -0
  72. {eqc_models-0.11.1.dist-info → eqc_models-0.13.0.dist-info}/top_level.txt +0 -0
@@ -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
  """
@@ -68,7 +68,6 @@ class ClusteringBase(QuadraticModel):
68
68
  self,
69
69
  sum_constraint=self._sum_constraint,
70
70
  relaxation_schedule=self.relaxation_schedule,
71
- solution_precision=1,
72
71
  num_samples=self.num_samples,
73
72
  )
74
73
 
@@ -78,7 +77,7 @@ class ClusteringBase(QuadraticModel):
78
77
 
79
78
  print(response)
80
79
 
81
- return sol
80
+ return sol, response
82
81
 
83
82
  def get_labels(self, sol):
84
83
  pass
@@ -66,7 +66,6 @@ class DecompBase(QuadraticModel):
66
66
  response = solver.solve(
67
67
  self,
68
68
  relaxation_schedule=self.relaxation_schedule,
69
- solution_precision=1,
70
69
  sum_constraint=self._sum_constraint,
71
70
  num_samples=self.num_samples,
72
71
  )
@@ -56,7 +56,6 @@ class RegressorBase(QuadraticModel):
56
56
  self,
57
57
  sum_constraint=self._sum_constraint,
58
58
  relaxation_schedule=self.relaxation_schedule,
59
- solution_precision=1,
60
59
  num_samples=self.num_samples,
61
60
  )
62
61
 
@@ -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,12 +1,16 @@
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)
5
+ from .mip import MIPMixin
6
+
7
+ class Dirac3MIPCloudSolver(MIPMixin, Dirac3ContinuousCloudSolver):
8
+ pass
9
+
10
+ class Dirac3MIPDirectSolver(MIPMixin, Dirac3DirectSolver):
11
+ pass
9
12
 
10
13
  __all__ = ["Dirac3DirectSolver", "Dirac1CloudSolver", "Dirac3CloudSolver",
11
14
  "EqcDirectSolver", "QciClientSolver", "Dirac3IntegerCloudSolver",
12
- "Dirac3ContinuousCloudSolver"]
15
+ "Dirac3ContinuousCloudSolver", "MILPMixin",
16
+ "Dirac3MIPCloudSolver", "Dirac3MIPDirectSolver"]
@@ -0,0 +1,76 @@
1
+ # (C) Quantum Computing Inc., 2025.
2
+ import logging
3
+ import numpy as np
4
+ from typing import Dict
5
+ from eqc_direct.client import EqcClient
6
+ from eqc_models.base.base import EqcModel, ModelSolver
7
+ from eqc_models.base.results import SolutionResults
8
+
9
+ log = logging.getLogger(name=__name__)
10
+
11
+
12
+ class Dirac3DirectSolver(ModelSolver):
13
+ ip_addr: str = "localhost"
14
+ port: str = "50051"
15
+ cert_file: str = None
16
+
17
+ def solve(
18
+ self,
19
+ model,
20
+ sum_constraint,
21
+ relaxation_schedule=1,
22
+ num_samples=1,
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
+ # add machine slacks
34
+ num_variables += model.machine_slacks
35
+ print("Num variables:", num_variables)
36
+
37
+ client = self.client
38
+ lock_id, startts, endts = client.wait_for_lock()
39
+
40
+ # assert lock["status_code"] == 0
41
+
42
+ # lock_id = lock["lock_id"]
43
+ response = None
44
+ try:
45
+ response = client.solve_sum_constrained(
46
+ coefficients,
47
+ indices,
48
+ num_variables,
49
+ num_samples=num_samples,
50
+ lock_id=lock_id,
51
+ relaxation_schedule=relaxation_schedule,
52
+ sum_constraint=sum_constraint,
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)
72
+
73
+ def makeResults(self, model : EqcModel, response : Dict):
74
+ """ Builds the results object """
75
+
76
+ return SolutionResults.from_eqcdirect_response(model, response, self)
@@ -0,0 +1,115 @@
1
+ import logging
2
+ import numpy as np
3
+ from eqc_models.base.base import EqcModel
4
+ from eqc_models.base.binaries import make_binary_penalty
5
+ from eqc_models.base.polynomial import PolynomialModel
6
+
7
+ log = logging.getLogger(name=__name__)
8
+
9
+ class MIPMixin:
10
+ """
11
+ Implements a solve method which intercepts the operator and builds a new
12
+ model with added terms for restriction of discrete variables with an
13
+ upper bound of 1 to take on only values 0 or 1 at minima.
14
+
15
+ Following the submission of a new model with the added penalties,
16
+ the solutions are updated to exclude added slack variables.
17
+
18
+ This is only supported with continuous-capable devices.
19
+
20
+ """
21
+
22
+ def solve(self, model : EqcModel, *args, **kwargs):
23
+ if model.is_discrete is None:
24
+ raise ValueError("Model solved with an MIP solver must have certain variables labeled discrete")
25
+ elif len([b for b in model.is_discrete if b])==0:
26
+ raise ValueError("Model solved with an MIP solver must have certain variables labeled discrete")
27
+ if kwargs.get("sum_constraint", None) is None:
28
+ raise ValueError("sum_constraint must be specified for MIP model sampling")
29
+ # get a polynomial
30
+ poly = model.polynomial
31
+ if hasattr(poly.coefficients, "tolist"):
32
+ coefficients = poly.coefficients.tolist()
33
+ else:
34
+ coefficients = list(poly.coefficients)
35
+ indices = poly.indices
36
+ old_n = model.n
37
+ log.debug("Model coefficients %d", len(coefficients))
38
+ log.debug("Model indices %d", len(indices))
39
+ log.debug("Model size %d", old_n)
40
+ if "penalty_multiplier" in kwargs:
41
+ penalty_multiplier = kwargs["penalty_multiplier"]
42
+ del kwargs["penalty_multiplier"]
43
+ else:
44
+ penalty_multiplier = getattr(model, "penalty_multiplier", 1)
45
+ log.debug("Binary enforcement penalty multiplier %f", penalty_multiplier)
46
+ bin_slacks = []
47
+ offset = 0
48
+ variables = model.variables
49
+ addtl_upper_bound = []
50
+ for i, v in enumerate(model.variables):
51
+ if model.is_discrete[i]:
52
+ bin_slacks.append(f"bin_slacks_{v}")
53
+ penalty_coeff, penalty_indices, penalty_offset = make_binary_penalty(i+1, len(variables)+len(bin_slacks), penalty_multiplier=penalty_multiplier)
54
+ log.debug("Adding penalties coeff: %s indices %s offset %s", penalty_coeff, penalty_indices, penalty_offset)
55
+ coefficients += penalty_coeff
56
+ indices += penalty_indices
57
+ offset += penalty_offset
58
+ addtl_upper_bound.append(1)
59
+ assert len(coefficients) == len(indices)
60
+ variables = variables + bin_slacks
61
+ log.debug("New model binary penalty slacks: %s", bin_slacks)
62
+ new_model = PolynomialModel(coefficients, indices)
63
+ new_model.variables = variables
64
+ log.debug("New model variables: %s", variables)
65
+ new_model.upper_bound = np.array(model.upper_bound.tolist() + addtl_upper_bound)
66
+ new_model.machine_slacks = model.machine_slacks
67
+ coefficients, indices = new_model.H
68
+ log.debug("New model coefficients %d", len(coefficients))
69
+ log.debug("New model indices %d", len(indices))
70
+ log.debug("New model size: %d", new_model.n)
71
+ response = super().solve(new_model, *args, **kwargs)
72
+ # translate the response into results
73
+ results = self.makeResults(new_model, response)
74
+ log.debug(results)
75
+ # update the results to relect the original model
76
+ solutions = results.solutions
77
+ for i in range(len(solutions)):
78
+ log.debug("SolutionResults solution: %s", solutions[i])
79
+ if hasattr(model, "evaluateObjective"):
80
+ new_objectives = []
81
+ else:
82
+ new_objectives = None
83
+ if hasattr(model, "evaluatePenalties"):
84
+ new_penalties = []
85
+ else:
86
+ new_penalties = None
87
+ new_solutions = []
88
+ new_energies = []
89
+ num_vars = len(solutions[0]) - len(bin_slacks)
90
+ log.debug("Num_vars %f", num_vars)
91
+ machine_slacks = model.machine_slacks
92
+ for i, solution in enumerate(solutions):
93
+ log.debug("%d - Raw solution %s", i, solution)
94
+ new_sol = [v for v in solution[:num_vars]]
95
+ new_sol = np.array(new_sol)
96
+ if machine_slacks > 0:
97
+ new_sol[-machine_slacks:] = solution[-machine_slacks:]
98
+ log.debug("%d - New solution %s", i, new_sol)
99
+ if new_objectives is not None:
100
+ try:
101
+ new_objectives.append(model.evaluateObjective(new_sol))
102
+ except NotImplementedError as err:
103
+ pass
104
+ if new_penalties is not None:
105
+ try:
106
+ new_penalties.append(model.evaluatePenalties(new_sol))
107
+ except NotImplementedError as err:
108
+ pass
109
+ new_solutions.append(new_sol)
110
+ new_energies.append(model.evaluate(new_sol))
111
+ results.solutions = new_solutions
112
+ results.penalties = new_penalties
113
+ results.objectives = new_objectives
114
+ results.energies = new_energies
115
+ return results
@@ -6,6 +6,7 @@ import numpy as np
6
6
  from qci_client import QciClient
7
7
  from eqc_models.base.base import ModelSolver, EqcModel
8
8
  from eqc_models.base.operators import OperatorNotAvailableError
9
+ from eqc_models.base.results import SolutionResults
9
10
 
10
11
  log = logging.getLogger(name=__name__)
11
12
 
@@ -77,6 +78,11 @@ class QciClientMixin:
77
78
  metrics = client.get_job_metrics(job_id=job_id)
78
79
  return metrics
79
80
 
81
+ def makeResults(self, model : EqcModel, response : Dict) -> SolutionResults:
82
+ """ Build the results object """
83
+
84
+ return SolutionResults.from_cloud_response(model, response, self)
85
+
80
86
  class Dirac1Mixin:
81
87
  sampler_type = "dirac-1"
82
88
  requires_operator = "qubo"
@@ -125,7 +131,6 @@ class Dirac3Mixin:
125
131
  max_upper_bound = 10000
126
132
  job_params_names = [
127
133
  "num_samples",
128
- "solution_precision",
129
134
  "relaxation_schedule",
130
135
  "mean_photon_number",
131
136
  "quantum_fluctuation_coefficient",
@@ -427,10 +432,9 @@ class Dirac3CloudSolver(Dirac3Mixin, QciClientSolver):
427
432
  Dirac3CloudSolver is a class that encapsulates the different calls to Qatalyst
428
433
  for Dirac-3 jobs. Currently, there are two different jobs, one for integer and
429
434
  another for continuous solutions. Calling the solve method with different arguments
430
- controls which job is submitted. The continuous job requires :code:`sum_constraint`
431
- and optionally takes the :code:`solution_precision` argument. The integer job
432
- does not accept either of these parameters, so specifying a sum constraint forces
433
- the job type to be continuous and not specifying it results in the integer job being
435
+ controls which job is submitted. The continuous job requires :code:`sum_constraint`.
436
+ The integer job does not accept this parameter, so specifying a sum constraint forces
437
+ the job type to be continuous, and not specifying it results in the integer job being
434
438
  called.
435
439
 
436
440
  Continuous Solver
@@ -454,8 +458,7 @@ class Dirac3CloudSolver(Dirac3Mixin, QciClientSolver):
454
458
  >>> model = QuadraticModel(C, J)
455
459
  >>> model.upper_bound = np.array([1, 1]) # set the domain maximum per variable
456
460
  >>> solver = Dirac3CloudSolver()
457
- >>> response = solver.solve(model, sum_constraint=1, relaxation_schedule=1,
458
- ... solution_precision=None) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
461
+ >>> response = solver.solve(model, sum_constraint=1, relaxation_schedule=1) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
459
462
  2... submitted... COMPLETED...
460
463
  >>> response["results"]["energies"][0] <= 1.0
461
464
  True
@@ -479,7 +482,6 @@ class Dirac3CloudSolver(Dirac3Mixin, QciClientSolver):
479
482
  tags: List = None,
480
483
  sum_constraint: float = None,
481
484
  relaxation_schedule: int = None,
482
- solution_precision: float = None,
483
485
  num_samples: int = 1,
484
486
  wait: bool = True,
485
487
  mean_photon_number: float = None,
@@ -503,11 +505,6 @@ class Dirac3CloudSolver(Dirac3Mixin, QciClientSolver):
503
505
  a predefined schedule indicator which sets parameters
504
506
  on the device to control the sampling through photon
505
507
  measurement
506
- solution_precision : float
507
- a value which, when not None, indicates the numerical
508
- precision desired in the solution: 1 for integer, 0.1
509
- for tenths place, 0.01 for hundreths and None for raw,
510
- only used with continuous solver
511
508
  num_samples : int
512
509
  the number of samples to take, defaults to 1
513
510
  wait : bool
@@ -540,7 +537,6 @@ class Dirac3CloudSolver(Dirac3Mixin, QciClientSolver):
540
537
  job_kwargs["relaxation_schedule"] = relaxation_schedule
541
538
  job_kwargs["mean_photon_number"] = mean_photon_number
542
539
  job_kwargs["quantum_fluctuation_coefficient"] = quantum_fluctuation_coefficient
543
- job_kwargs["solution_precision"] = solution_precision
544
540
  job_type = "sample-" + self.job_type
545
541
  return super().solve(
546
542
  model,
@@ -663,8 +659,7 @@ class Dirac3ContinuousCloudSolver(Dirac3Mixin, QciClientSolver):
663
659
  >>> model = QuadraticModel(C, J)
664
660
  >>> model.upper_bound = np.array([1, 1]) # set the domain maximum per variable
665
661
  >>> solver = Dirac3ContinuousCloudSolver()
666
- >>> response = solver.solve(model, sum_constraint=1, relaxation_schedule=1,
667
- ... solution_precision=None) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
662
+ >>> response = solver.solve(model, sum_constraint=1, relaxation_schedule=1) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
668
663
  2... submitted... COMPLETED...
669
664
  >>> response["results"]["energies"][0] <= 1.0
670
665
  True
@@ -680,7 +675,6 @@ class Dirac3ContinuousCloudSolver(Dirac3Mixin, QciClientSolver):
680
675
  tags: List = None,
681
676
  sum_constraint: float = None,
682
677
  relaxation_schedule: int = None,
683
- solution_precision: float = None,
684
678
  num_samples: int = 1,
685
679
  wait: bool = True,
686
680
  mean_photon_number: float = None,
@@ -703,10 +697,6 @@ class Dirac3ContinuousCloudSolver(Dirac3Mixin, QciClientSolver):
703
697
  a predefined schedule indicator which sets parameters
704
698
  on the device to control the sampling through photon
705
699
  measurement
706
- solution_precision : float
707
- a value which, when not None, indicates the numerical
708
- precision desired in the solution: 1 for integer, 0.1
709
- for tenths place, 0.01 for hundreths and None for raw
710
700
  num_samples : int
711
701
  the number of samples to take, defaults to 1
712
702
  wait : bool
@@ -744,7 +734,6 @@ class Dirac3ContinuousCloudSolver(Dirac3Mixin, QciClientSolver):
744
734
  num_samples=num_samples,
745
735
  wait=wait,
746
736
  job_type=job_type,
747
- solution_precision=solution_precision,
748
737
  sum_constraint=sum_constraint,
749
738
  relaxation_schedule=relaxation_schedule,
750
739
  mean_photon_number=mean_photon_number,
@@ -0,0 +1,47 @@
1
+ import os
2
+ import json
3
+ import time
4
+
5
+ class ResponseLogMixin:
6
+
7
+ def logResponse(self, response, model, metrics=None):
8
+ record = {
9
+ "response": response,
10
+ "metrics": metrics,
11
+ "size": model.n,
12
+ "name": model.__class__.__name__,
13
+ "upper_bound": [u for u in model.upper_bound],
14
+ "machine_slacks": model.machine_slacks,
15
+ "penalty_multiplier": getattr(model, "penalty_multiplier", None)
16
+ }
17
+ fname = f"response-{time.time()}.json"
18
+ dirname = self.getLogDir()
19
+ fullname = os.path.join(dirname, fname)
20
+ if not os.access(fullname, os.W_OK):
21
+ log.warn(f"Response will not be logged because {fullname} is not writable")
22
+ return
23
+ elif os.path.exists(fullname):
24
+ log.warn(f"Response will not be logged because {fullname} exists")
25
+ return
26
+ with open(fullname, "w") as fp:
27
+ log.debug(f"Wrote response to {fullname}")
28
+ json.dump(record, fp)
29
+
30
+ def getLogDir(self):
31
+ """ Ensure the logging directory exists and return the path """
32
+
33
+ dirname = os.path.expanduser("~/.eqc-models")
34
+ if not os.path.exists(dirname):
35
+ try:
36
+ os.mkdir(dirname)
37
+ except OSError:
38
+ log.warn(f"Responses will not be logged because {dirname} is not writable")
39
+ return None
40
+ dirname = os.path.join(dirname, "responses")
41
+ if not os.path.exists(dirname):
42
+ try>
43
+ os.mkdir(dirname)
44
+ except OSError:
45
+ log.warn(f"Responses will not be logged because {dirname} is not writable")
46
+ return None
47
+ return dirname
@@ -1,9 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eqc-models
3
- Version: 0.11.1
3
+ Version: 0.13.0
4
4
  Summary: Optimization and ML modeling package targeting EQC devices
5
- Author: Quantum Computing Inc.
6
- Author-email: support@quantumcomputinginc.com
5
+ Author-email: "Quantum Computing Inc." <support@quantumcomputinginc.com>
7
6
  Project-URL: Homepage, https://quantumcomputinginc.com
8
7
  Project-URL: Documentation, https://quantumcomputinginc.com/learn/support/software-packages/
9
8
  Project-URL: Issues, https://support.quantumcomputinginc.com/
@@ -12,12 +11,11 @@ Description-Content-Type: text/markdown
12
11
  License-File: LICENSE.txt
13
12
  Requires-Dist: numpy<2,>=1.22.1
14
13
  Requires-Dist: networkx<3,>=2.6.3
15
- Requires-Dist: pandas>=2.1.0
16
- Requires-Dist: scikit-learn>=1.2.1
17
- Requires-Dist: qci-client<5,>=4.3.0
18
- Requires-Dist: emucore-direct==1.0.6
19
- Provides-Extra: direct
20
- Requires-Dist: eqc-direct<2,>=1.3.0; extra == "direct"
14
+ Requires-Dist: pandas<3,>=2.1.0
15
+ Requires-Dist: scikit-learn<2,>=1.2.1
16
+ Requires-Dist: qci-client<6,>=5
17
+ Requires-Dist: emucore-direct==1.0.7
18
+ Requires-Dist: eqc-direct==2.0.2
21
19
  Provides-Extra: dev
22
20
  Requires-Dist: pytest<8,>=7.1.0; extra == "dev"
23
21
  Requires-Dist: pytest-cov; extra == "dev"
@@ -0,0 +1,69 @@
1
+ eqc_models-0.13.0.data/platlib/compile_extensions.py,sha256=ivFZ87WFzBITU7IwK_72C41MDNMortJIF8tKevm2aW4,1946
2
+ eqc_models-0.13.0.data/platlib/eqc_models/__init__.py,sha256=WPUijJz2-4UZU-ZTqBofDc-Yaah24geHdmF16SkwIj4,683
3
+ eqc_models-0.13.0.data/platlib/eqc_models/decoding.py,sha256=G3JgbIFzvZ3DIKW0kZ1JeTMIZmrc8hy9kzdbX2Xv5Og,637
4
+ eqc_models-0.13.0.data/platlib/eqc_models/algorithms/__init__.py,sha256=lzQoMMSs2QTqp5suEYNvcQaSEN16d0LwIsZ1mRstumU,135
5
+ eqc_models-0.13.0.data/platlib/eqc_models/algorithms/base.py,sha256=qfQQTwuVyewn7Qpg1_SVoD_7TsdA8vdwSKGqOeZSmNI,204
6
+ eqc_models-0.13.0.data/platlib/eqc_models/algorithms/penaltymultiplier.py,sha256=SndGxCZDS3JTaxFOPJpTBumFdIKcB0dKwSHwfl_BI6o,7845
7
+ eqc_models-0.13.0.data/platlib/eqc_models/allocation/__init__.py,sha256=op_udrapTlWrakTuQId3M0ggo-Y1w4nGJLPcYKOQ-8I,239
8
+ eqc_models-0.13.0.data/platlib/eqc_models/allocation/allocation.py,sha256=PAQn4M75Zegeoy0i6r3hycWs4TKeRglHk05TvwZOoLk,15506
9
+ eqc_models-0.13.0.data/platlib/eqc_models/allocation/portbase.py,sha256=BTnYYduHydPbrE2yQr_Sgv3XJACH_GpIJstuMrfGqCU,3269
10
+ eqc_models-0.13.0.data/platlib/eqc_models/allocation/portmomentum.py,sha256=oMod63rNDC-01dLZjmhUb24SN3_GVgfc6CItgQL_obI,3756
11
+ eqc_models-0.13.0.data/platlib/eqc_models/assignment/__init__.py,sha256=WDlTjWGu75UTxuNUPGNVGoMaYvYILWzZOuS-o72n054,160
12
+ eqc_models-0.13.0.data/platlib/eqc_models/assignment/qap.py,sha256=WMiQQmTORsgi2w7kbmMA1xo-93dESLECWqYTF-zkmTs,2963
13
+ eqc_models-0.13.0.data/platlib/eqc_models/assignment/resource.py,sha256=Ux9e3Badty6bFMqRaLKAGbVRUtb1k1r1_E_2ajOhgb4,6883
14
+ eqc_models-0.13.0.data/platlib/eqc_models/assignment/setpartition.py,sha256=5SQxF_ZlQk4ubWf5_3TgL83k01hAakUP-5AydlD-BvE,161
15
+ eqc_models-0.13.0.data/platlib/eqc_models/base/__init__.py,sha256=wKBppDk1lBiDvGOFnNpzu4lh7n4dQiyd_x3lNQJumTw,2952
16
+ eqc_models-0.13.0.data/platlib/eqc_models/base/base.py,sha256=3ESnRDa9KrOmyGFtDHP10X-TNBnOaDnBQ549uVcSB34,6721
17
+ eqc_models-0.13.0.data/platlib/eqc_models/base/binaries.py,sha256=rS-EUl2vzlDRTvHQ9Qn6SkyXfpyLMik50wh-h_bX5Qs,726
18
+ eqc_models-0.13.0.data/platlib/eqc_models/base/constraints.py,sha256=BKTQlkITRE8C-_ix6pVWbIK42RxrLsmzS3e8faD5Y7U,9540
19
+ eqc_models-0.13.0.data/platlib/eqc_models/base/operators.py,sha256=9nCeN6fRP-_YBfs-Gm57D-O_376qcOQiqGDuVlSlf00,7392
20
+ eqc_models-0.13.0.data/platlib/eqc_models/base/polyeval.c,sha256=wu3gWbakYpq0kWgmJfj5XiEhPpk3Dc54xHNMGwKdXUE,483061
21
+ eqc_models-0.13.0.data/platlib/eqc_models/base/polyeval.cpython-310-darwin.so,sha256=MvVkAT8p-rYhwEo7-rWGqgPyi-tb_S97PvX4cWXroTs,109312
22
+ eqc_models-0.13.0.data/platlib/eqc_models/base/polyeval.pyx,sha256=76Bf99Jt1_rLh5byrZxAjavE2F4_yCysirViqOBFIXw,2547
23
+ eqc_models-0.13.0.data/platlib/eqc_models/base/polynomial.py,sha256=dkRs05mkItOwvWQgZjdAPG93OP3Pkd8jnJ0a2e1t-lU,13846
24
+ eqc_models-0.13.0.data/platlib/eqc_models/base/quadratic.py,sha256=IKjd-tL6pQosl217knS_ul2BXpk5a8ZZiSUzvKPg8S8,8082
25
+ eqc_models-0.13.0.data/platlib/eqc_models/base/results.py,sha256=P_tetLKJm-xWl6k00C0TFSTinq8jEeolwGsRTwsc-Zo,8777
26
+ eqc_models-0.13.0.data/platlib/eqc_models/combinatorics/__init__.py,sha256=BhzcVxwpWu2b4jIe0bmPzD5VmSyzwp0oW2q9iYx2IUs,167
27
+ eqc_models-0.13.0.data/platlib/eqc_models/combinatorics/setcover.py,sha256=T5hXoE9Ecw3mTHPLmifBwTzpF_4MhoCUgo2rkSOWt5s,3396
28
+ eqc_models-0.13.0.data/platlib/eqc_models/combinatorics/setpartition.py,sha256=ZD69kgEYSU3KWnx0b4MVCP8XSxbA_VCXOW22_Yssl_M,6254
29
+ eqc_models-0.13.0.data/platlib/eqc_models/graph/__init__.py,sha256=mpueOOcKklmtw1A3yUsjFNXU5DJ5XnItmGJKapaBLPg,392
30
+ eqc_models-0.13.0.data/platlib/eqc_models/graph/base.py,sha256=K9d7hLgLuBtywEdK9Rz1dUV70Xtf-oVrwqtHyzXK7k4,2117
31
+ eqc_models-0.13.0.data/platlib/eqc_models/graph/hypergraph.py,sha256=ABvutT0NOdIEpUF4TjUzboE4Y_J5iUZyj6-AzKr4R28,13268
32
+ eqc_models-0.13.0.data/platlib/eqc_models/graph/maxcut.py,sha256=o8xVsAwTa9jcpmsIoCQ5z7HSstVdraT8TENomdT519o,4132
33
+ eqc_models-0.13.0.data/platlib/eqc_models/graph/maxkcut.py,sha256=rEDBjto2MbuPh4c0RwTOZoVffKgcriqHNOZAIuBlclQ,4654
34
+ eqc_models-0.13.0.data/platlib/eqc_models/graph/partition.py,sha256=HMpRRipLp14x8pHucY-g6fU7v0PGoy1pf_KpzbanfD0,5800
35
+ eqc_models-0.13.0.data/platlib/eqc_models/graph/rcshortestpath.py,sha256=g5sy8pRk6c5x4nHVrs9vd0DjDxqlaLDkSytsiIp1hRw,3127
36
+ eqc_models-0.13.0.data/platlib/eqc_models/graph/shortestpath.py,sha256=p0NMGQt9pGbRQwu2pSIXXetSJfHB9K7K0rXP5JvDpQE,6443
37
+ eqc_models-0.13.0.data/platlib/eqc_models/ml/__init__.py,sha256=CLfraacr0FrD5ynxlNB6cyNy0lpbavcQT45TvkDrNvY,369
38
+ eqc_models-0.13.0.data/platlib/eqc_models/ml/classifierbase.py,sha256=1D6EYgiEqbtoXpBHnCaBqPDXKEjsIpJpM5UTIGxumfk,3080
39
+ eqc_models-0.13.0.data/platlib/eqc_models/ml/classifierqboost.py,sha256=oxYnex7Z_iXglupqmMN9bK6gU1DxKcHOo03fLCmELfQ,19456
40
+ eqc_models-0.13.0.data/platlib/eqc_models/ml/classifierqsvm.py,sha256=ELKAdOMExeNjJIJCHd28bf7xQYBI2TpQDGkifldThkU,12120
41
+ eqc_models-0.13.0.data/platlib/eqc_models/ml/clustering.py,sha256=KD8mv_xY9-pRGKDRgeLDO3e38cjftzca4SUBvN4__-I,9522
42
+ eqc_models-0.13.0.data/platlib/eqc_models/ml/clusteringbase.py,sha256=mBlNe72QJmiGUhgq_jepHauNvANWhG0hEZQY2EHWKtA,2604
43
+ eqc_models-0.13.0.data/platlib/eqc_models/ml/cvqboost_hamiltonian.pyx,sha256=3PMmEJ_xfmmWXGfire0t-WASnmKj6-CblufgQ2NTARo,2111
44
+ eqc_models-0.13.0.data/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.c,sha256=ZoKgm_uGjTewhk4W6s-x8QoFuZO0KVkxILIFh6JKsoI,1851
45
+ eqc_models-0.13.0.data/platlib/eqc_models/ml/cvqboost_hamiltonian_c_func.h,sha256=aOImMG5pziUnZxGpDXyWjLrvcY7ZdsczwwSQ2ay4T88,272
46
+ eqc_models-0.13.0.data/platlib/eqc_models/ml/decomposition.py,sha256=VbYAM6tJ0FSwvSezhHDrhpQjqbChVED9DAJPJd98I4A,9475
47
+ eqc_models-0.13.0.data/platlib/eqc_models/ml/forecast.py,sha256=fFcBxQK9ZryfEuyvlr9HXicHoZRzLFybimYYttzhI9E,7403
48
+ eqc_models-0.13.0.data/platlib/eqc_models/ml/forecastbase.py,sha256=s-6nUMvtYqG07r7MmmkFVj8_QqgeGkD-HVoEEDTE2bk,3654
49
+ eqc_models-0.13.0.data/platlib/eqc_models/ml/regressor.py,sha256=LA1woXCnefG0wfoOxilX1kszgCUmfNcbQgs_WZ4Ai0o,5683
50
+ eqc_models-0.13.0.data/platlib/eqc_models/ml/regressorbase.py,sha256=ZG1lCek3VEH8iONa5N-sNxRa_7X9gO3Tg_-uX2ItLnc,2075
51
+ eqc_models-0.13.0.data/platlib/eqc_models/ml/reservoir.py,sha256=cPRvpCaWLYTBkui35jCssHcOPQgSQZallrG6Ac9djVI,2827
52
+ eqc_models-0.13.0.data/platlib/eqc_models/process/base.py,sha256=QmwbPRc9w9Yr7cwPvdnV6LBdgajif_8WGYGfwApvO34,443
53
+ eqc_models-0.13.0.data/platlib/eqc_models/process/mpc.py,sha256=V7RlA6t08IayV-VKkpK4mC01Lvk3ZTD-HlFYk60snks,645
54
+ eqc_models-0.13.0.data/platlib/eqc_models/sequence/__init__.py,sha256=VXlYufO3GYFsM00oii9Cite2WsQEF8XTwRcjLPH_Zlg,92
55
+ eqc_models-0.13.0.data/platlib/eqc_models/sequence/tsp.py,sha256=YM641FTyK5NkgRGxHrU1QmMkEU0gf77nEmIElTqa6Qw,7680
56
+ eqc_models-0.13.0.data/platlib/eqc_models/solvers/__init__.py,sha256=Q6QZkkeji_QyeBmgMT5qUs7mzdjK8hPUxw3zLqPxq00,677
57
+ eqc_models-0.13.0.data/platlib/eqc_models/solvers/eqcdirect.py,sha256=CUchx3GH0VqNaE6SlZN75tH6CoztwGdGbLuhLdUr85s,2319
58
+ eqc_models-0.13.0.data/platlib/eqc_models/solvers/mip.py,sha256=jdH2nHUZ5FZ2LCW2Tm08PjWfh5LM_SM0x5tLvlWNM_w,5270
59
+ eqc_models-0.13.0.data/platlib/eqc_models/solvers/qciclient.py,sha256=ore3YcZ9GAoLfdkYQUgo7XLU1WKvobHzl22DuwINWj8,26677
60
+ eqc_models-0.13.0.data/platlib/eqc_models/solvers/responselog.py,sha256=Vl0ZDYixwH2OnuCECP-TRwJ6PGfvPodWUgpvYOvYzRk,1735
61
+ eqc_models-0.13.0.data/platlib/eqc_models/utilities/__init__.py,sha256=SI2U7JKmPWSiq-F1WcSyfd7l9V6nbOZv_p8quMAZaT0,340
62
+ eqc_models-0.13.0.data/platlib/eqc_models/utilities/fileio.py,sha256=alWPTfjGFx6Iio9HZAAWtYcLmZsBBifg6S6_YbFMQhk,1088
63
+ eqc_models-0.13.0.data/platlib/eqc_models/utilities/polynomial.py,sha256=blXfu7Ehz9lT4nEmIinRzJOL27_qUHSbQ57zxmwDJCA,4735
64
+ eqc_models-0.13.0.data/platlib/eqc_models/utilities/qplib.py,sha256=Do-MjmCFdI5HyDOAjfoz4_5lugySLMBlMAWDLUWx2OA,15796
65
+ eqc_models-0.13.0.dist-info/licenses/LICENSE.txt,sha256=8eh0oqsNNVR1Jk-13gkqRRSo2axtUU5kp2KzH4f9u3U,11354
66
+ eqc_models-0.13.0.dist-info/METADATA,sha256=KOi9xU2l9f1w678joAy7798-Z08D0CAXIF4-IkUtWcg,7082
67
+ eqc_models-0.13.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
68
+ eqc_models-0.13.0.dist-info/top_level.txt,sha256=9ZfFeKNEvkRlKWoUnfcZ9TzmTdgdsuPEnTPy11Hqf4Q,30
69
+ eqc_models-0.13.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"]