eqc-models 0.10.1__tar.gz → 0.10.2__tar.gz

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 (123) hide show
  1. {eqc_models-0.10.1/eqc_models.egg-info → eqc_models-0.10.2}/PKG-INFO +1 -1
  2. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/__init__.py +2 -1
  3. eqc_models-0.10.2/eqc_models/assignment/setpartition.py +4 -0
  4. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/base/base.py +44 -4
  5. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/base/polynomial.py +7 -3
  6. eqc_models-0.10.2/eqc_models/combinatorics/__init__.py +6 -0
  7. {eqc_models-0.10.1/eqc_models/assignment → eqc_models-0.10.2/eqc_models/combinatorics}/setpartition.py +2 -0
  8. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/graph/maxkcut.py +26 -68
  9. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/solvers/qciclient.py +11 -2
  10. {eqc_models-0.10.1 → eqc_models-0.10.2/eqc_models.egg-info}/PKG-INFO +1 -1
  11. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models.egg-info/SOURCES.txt +1 -0
  12. eqc_models-0.10.1/eqc_models/combinatorics/__init__.py +0 -5
  13. {eqc_models-0.10.1 → eqc_models-0.10.2}/.gitlab-ci.yml +0 -0
  14. {eqc_models-0.10.1 → eqc_models-0.10.2}/LICENSE.txt +0 -0
  15. {eqc_models-0.10.1 → eqc_models-0.10.2}/MANIFEST.in +0 -0
  16. {eqc_models-0.10.1 → eqc_models-0.10.2}/README.md +0 -0
  17. {eqc_models-0.10.1 → eqc_models-0.10.2}/compile_extensions.py +0 -0
  18. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/Makefile +0 -0
  19. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/build/html/_static/basic.css +0 -0
  20. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/build/html/_static/css/badge_only.css +0 -0
  21. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/build/html/_static/css/theme.css +0 -0
  22. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/build/html/_static/custom.css +0 -0
  23. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/build/html/_static/file.png +0 -0
  24. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/build/html/_static/minus.png +0 -0
  25. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/build/html/_static/plus.png +0 -0
  26. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/build/html/_static/pygments.css +0 -0
  27. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/build/html/_static/white_logo.png +0 -0
  28. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/make.bat +0 -0
  29. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/source/_static/custom.css +0 -0
  30. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/source/_static/white_logo.png +0 -0
  31. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/source/conf.py +0 -0
  32. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/source/dependencies.rst +0 -0
  33. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/source/eqc_models.rst +0 -0
  34. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/source/index.rst +0 -0
  35. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/source/modules.rst +0 -0
  36. {eqc_models-0.10.1 → eqc_models-0.10.2}/docs/source/usage.rst +0 -0
  37. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/algorithms/__init__.py +0 -0
  38. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/algorithms/base.py +0 -0
  39. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/algorithms/penaltymultiplier.py +0 -0
  40. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/allocation/__init__.py +0 -0
  41. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/allocation/allocation.py +0 -0
  42. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/allocation/portbase.py +0 -0
  43. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/allocation/portmomentum.py +0 -0
  44. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/assignment/__init__.py +0 -0
  45. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/assignment/qap.py +0 -0
  46. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/base/__init__.py +0 -0
  47. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/base/constraints.py +0 -0
  48. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/base/operators.py +0 -0
  49. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/base/polyeval.c +0 -0
  50. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/base/polyeval.pyx +0 -0
  51. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/base/quadratic.py +0 -0
  52. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/combinatorics/setcover.py +0 -0
  53. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/decoding.py +0 -0
  54. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/graph/__init__.py +0 -0
  55. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/graph/base.py +0 -0
  56. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/graph/hypergraph.py +0 -0
  57. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/graph/maxcut.py +0 -0
  58. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/graph/partition.py +0 -0
  59. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/ml/__init__.py +0 -0
  60. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/ml/classifierbase.py +0 -0
  61. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/ml/classifierqboost.py +0 -0
  62. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/ml/classifierqsvm.py +0 -0
  63. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/ml/clustering.py +0 -0
  64. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/ml/clusteringbase.py +0 -0
  65. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/ml/cvqboost_hamiltonian.pyx +0 -0
  66. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/ml/cvqboost_hamiltonian_c_func.c +0 -0
  67. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/ml/cvqboost_hamiltonian_c_func.h +0 -0
  68. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/ml/decomposition.py +0 -0
  69. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/ml/forecast.py +0 -0
  70. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/ml/forecastbase.py +0 -0
  71. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/ml/regressor.py +0 -0
  72. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/ml/regressorbase.py +0 -0
  73. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/ml/reservoir.py +0 -0
  74. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/sequence/__init__.py +0 -0
  75. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/sequence/tsp.py +0 -0
  76. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/solvers/__init__.py +0 -0
  77. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/utilities/__init__.py +0 -0
  78. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/utilities/fileio.py +0 -0
  79. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/utilities/polynomial.py +0 -0
  80. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models/utilities/qplib.py +0 -0
  81. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models.egg-info/dependency_links.txt +0 -0
  82. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models.egg-info/requires.txt +0 -0
  83. {eqc_models-0.10.1 → eqc_models-0.10.2}/eqc_models.egg-info/top_level.txt +0 -0
  84. {eqc_models-0.10.1 → eqc_models-0.10.2}/pyproject.toml +0 -0
  85. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/binary_job_example.py +0 -0
  86. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/c6h6_graph_clustering.py +0 -0
  87. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/clustering.py +0 -0
  88. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/continuous_job_example.py +0 -0
  89. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/duality_example.py +0 -0
  90. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/graph_clustering.py +0 -0
  91. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/graph_partitioning.py +0 -0
  92. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/hamiltonian_to_polynomial.py +0 -0
  93. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/hypergraph.py +0 -0
  94. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/integer_job_example.py +0 -0
  95. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/karate_graph_clustering.py +0 -0
  96. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/lin_reg_dirac3.py +0 -0
  97. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/mackey_glass_cell_production_series.csv +0 -0
  98. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/pca_iris_dirac3.py +0 -0
  99. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/port_opt_dirac3.py +0 -0
  100. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/qboost_iris_dirac3.py +0 -0
  101. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/qplib_benchmark_config.py +0 -0
  102. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/qplib_reader.py +0 -0
  103. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/qplib_runner.py +0 -0
  104. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/qsvm_iris_dirac3.py +0 -0
  105. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/reservoir_forecast.py +0 -0
  106. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/rundoctests.py +0 -0
  107. {eqc_models-0.10.1 → eqc_models-0.10.2}/scripts/utils.py +0 -0
  108. {eqc_models-0.10.1 → eqc_models-0.10.2}/setup.cfg +0 -0
  109. {eqc_models-0.10.1 → eqc_models-0.10.2}/test/doctest_base.py +0 -0
  110. {eqc_models-0.10.1 → eqc_models-0.10.2}/test/testallocationmodel.py +0 -0
  111. {eqc_models-0.10.1 → eqc_models-0.10.2}/test/testconstraint.py +0 -0
  112. {eqc_models-0.10.1 → eqc_models-0.10.2}/test/testcvqboost.py +0 -0
  113. {eqc_models-0.10.1 → eqc_models-0.10.2}/test/testeqcdirectsolver.py +0 -0
  114. {eqc_models-0.10.1 → eqc_models-0.10.2}/test/testgraphpartitionmodel.py +0 -0
  115. {eqc_models-0.10.1 → eqc_models-0.10.2}/test/testhypergraphmodel.py +0 -0
  116. {eqc_models-0.10.1 → eqc_models-0.10.2}/test/testmaxcutmodel.py +0 -0
  117. {eqc_models-0.10.1 → eqc_models-0.10.2}/test/testpolynomialmodel.py +0 -0
  118. {eqc_models-0.10.1 → eqc_models-0.10.2}/test/testqapmodel.py +0 -0
  119. {eqc_models-0.10.1 → eqc_models-0.10.2}/test/testqciclientsolver.py +0 -0
  120. {eqc_models-0.10.1 → eqc_models-0.10.2}/test/testquadraticmodel.py +0 -0
  121. {eqc_models-0.10.1 → eqc_models-0.10.2}/test/testsetcovermodel.py +0 -0
  122. {eqc_models-0.10.1 → eqc_models-0.10.2}/test/testsetpartitionmodel.py +0 -0
  123. {eqc_models-0.10.1 → eqc_models-0.10.2}/test/testtsp.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: eqc-models
3
- Version: 0.10.1
3
+ Version: 0.10.2
4
4
  Summary: Optimization and ML modeling package targeting EQC devices
5
5
  Author: Quantum Computing Inc.
6
6
  Author-email: support@quantumcomputinginc.com
@@ -8,8 +8,9 @@ from .base import QuadraticModel, PolynomialModel
8
8
  from .solvers import (Dirac1CloudSolver, Dirac3CloudSolver, Dirac3DirectSolver)
9
9
  from .allocation import AllocationModel, AllocationModelX, ResourceRuleEnum
10
10
  from .assignment import QAPModel
11
+ from .combinatorics import SetCoverModel, SetPartitionModel
11
12
 
12
13
  __all__ = ["QuadraticModel", "PolynomialModel", "Dirac1CloudSolver",
13
14
  "Dirac3CloudSolver", "AllocationModel", "AllocationModelX",
14
15
  "Dirac3DirectSolver", "ResourceRuleEnum",
15
- "QAPModel"]
16
+ "QAPModel", "SetPartitionModel", "SetCoverModel"]
@@ -0,0 +1,4 @@
1
+ from ..combinatorics import SetPartitionModel
2
+ import warnings
3
+
4
+ warnings.warn("import of SetPartitionModel through assignment is deprecated", DeprecationWarning)
@@ -42,12 +42,50 @@ class EqcModel:
42
42
  _H = None
43
43
  _machine_slacks = 0
44
44
 
45
- def decode(self, solution : np.ndarray) -> np.ndarray:
46
- """ Manipulate the solution to match the variable count """
45
+ def decode(self, solution : np.ndarray, from_encoding : str=None) -> np.ndarray:
46
+ """
47
+ Manipulate the solution to match the variable count. Optionally,
48
+ a log-encoded solution vector can be translated into a vector
49
+ with integral values.
50
+
51
+ Parameters
52
+ -----------
53
+
54
+ solution : np.ndarray
55
+ 1d solution vector
56
+
57
+ from_encoding : str
58
+ string indicating if the vector is an encoding of particular type. The
59
+ text 'qubo' is the only option that does anything for now.
60
+
61
+ >>> model = EqcModel()
62
+ >>> ub = np.array([1, 2, 5])
63
+ >>> model.upper_bound = ub
64
+ >>> model.machine_slacks = 1
65
+ >>> solution = np.array([1, 1, 1, 1, 0, 1, 0]) # this solution has a 3, which violates the upper bound, but decode doesn't care
66
+ >>> model.decode(solution, "qubo")
67
+ array([1, 3, 5])
68
+
69
+ """
47
70
 
71
+ solution = np.array(solution)
48
72
  # ignore any slacks that may have been added during encoding
49
- solution = solution[:-self.machine_slacks]
50
-
73
+ if self.machine_slacks > 0:
74
+ solution = solution[:-self.machine_slacks]
75
+ if from_encoding == "qubo":
76
+ ub = self.upper_bound
77
+ en = solution.shape[0]
78
+ assert en > 0
79
+ n = ub.shape[0]
80
+ linear_operator = np.zeros((n,en))
81
+ j = 0
82
+ for i in range(self.n):
83
+ m = int(np.floor(np.log2(ub[i]))+1)
84
+ bits = 2**np.arange(m)
85
+ assert j+m <= linear_operator.shape[1]+2, f"Invalid slice for i={i} {j}:{j+m}"
86
+ linear_operator[i,j:j+m] = bits
87
+ j += m
88
+ solution = (linear_operator@solution).astype(np.int64)
51
89
  return solution
52
90
 
53
91
  @property
@@ -64,6 +102,8 @@ class EqcModel:
64
102
  value = np.array(value)
65
103
  if (value != value.astype(np.int64)).any():
66
104
  raise ValueError("Upper bound values must be integer")
105
+ if (value==0).any():
106
+ raise ValueError("Zero values are not allowed as an upper_bound.")
67
107
  self._upper_bound = value.astype(np.int64)
68
108
 
69
109
  @property
@@ -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,6 @@
1
+ # (C) Quantum Computing Inc., 2024.
2
+
3
+ from .setcover import SetCoverModel
4
+ from .setpartition import SetPartitionModel
5
+
6
+ __all__ = ["SetCoverModel", "SetPartitionModel"]
@@ -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
@@ -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
1
  Metadata-Version: 2.2
2
2
  Name: eqc-models
3
- Version: 0.10.1
3
+ Version: 0.10.2
4
4
  Summary: Optimization and ML modeling package targeting EQC devices
5
5
  Author: Quantum Computing Inc.
6
6
  Author-email: support@quantumcomputinginc.com
@@ -50,6 +50,7 @@ eqc_models/base/polynomial.py
50
50
  eqc_models/base/quadratic.py
51
51
  eqc_models/combinatorics/__init__.py
52
52
  eqc_models/combinatorics/setcover.py
53
+ eqc_models/combinatorics/setpartition.py
53
54
  eqc_models/graph/__init__.py
54
55
  eqc_models/graph/base.py
55
56
  eqc_models/graph/hypergraph.py
@@ -1,5 +0,0 @@
1
- # (C) Quantum Computing Inc., 2024.
2
-
3
- from .setcover import SetCoverModel
4
-
5
- __all__ = ["SetCoverModel"]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes