eqc-models 0.9.8__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 (52) hide show
  1. eqc_models-0.9.8.data/platlib/compile_extensions.py +23 -0
  2. eqc_models-0.9.8.data/platlib/eqc_models/__init__.py +15 -0
  3. eqc_models-0.9.8.data/platlib/eqc_models/algorithms/__init__.py +4 -0
  4. eqc_models-0.9.8.data/platlib/eqc_models/algorithms/base.py +10 -0
  5. eqc_models-0.9.8.data/platlib/eqc_models/algorithms/penaltymultiplier.py +169 -0
  6. eqc_models-0.9.8.data/platlib/eqc_models/allocation/__init__.py +6 -0
  7. eqc_models-0.9.8.data/platlib/eqc_models/allocation/allocation.py +367 -0
  8. eqc_models-0.9.8.data/platlib/eqc_models/allocation/portbase.py +128 -0
  9. eqc_models-0.9.8.data/platlib/eqc_models/allocation/portmomentum.py +137 -0
  10. eqc_models-0.9.8.data/platlib/eqc_models/assignment/__init__.py +5 -0
  11. eqc_models-0.9.8.data/platlib/eqc_models/assignment/qap.py +82 -0
  12. eqc_models-0.9.8.data/platlib/eqc_models/assignment/setpartition.py +170 -0
  13. eqc_models-0.9.8.data/platlib/eqc_models/base/__init__.py +72 -0
  14. eqc_models-0.9.8.data/platlib/eqc_models/base/base.py +150 -0
  15. eqc_models-0.9.8.data/platlib/eqc_models/base/constraints.py +276 -0
  16. eqc_models-0.9.8.data/platlib/eqc_models/base/operators.py +201 -0
  17. eqc_models-0.9.8.data/platlib/eqc_models/base/polyeval.c +11363 -0
  18. eqc_models-0.9.8.data/platlib/eqc_models/base/polyeval.cpython-310-darwin.so +0 -0
  19. eqc_models-0.9.8.data/platlib/eqc_models/base/polyeval.pyx +72 -0
  20. eqc_models-0.9.8.data/platlib/eqc_models/base/polynomial.py +274 -0
  21. eqc_models-0.9.8.data/platlib/eqc_models/base/quadratic.py +250 -0
  22. eqc_models-0.9.8.data/platlib/eqc_models/decoding.py +20 -0
  23. eqc_models-0.9.8.data/platlib/eqc_models/graph/__init__.py +5 -0
  24. eqc_models-0.9.8.data/platlib/eqc_models/graph/base.py +63 -0
  25. eqc_models-0.9.8.data/platlib/eqc_models/graph/hypergraph.py +307 -0
  26. eqc_models-0.9.8.data/platlib/eqc_models/graph/maxcut.py +155 -0
  27. eqc_models-0.9.8.data/platlib/eqc_models/graph/maxkcut.py +184 -0
  28. eqc_models-0.9.8.data/platlib/eqc_models/ml/__init__.py +15 -0
  29. eqc_models-0.9.8.data/platlib/eqc_models/ml/classifierbase.py +99 -0
  30. eqc_models-0.9.8.data/platlib/eqc_models/ml/classifierqboost.py +423 -0
  31. eqc_models-0.9.8.data/platlib/eqc_models/ml/classifierqsvm.py +237 -0
  32. eqc_models-0.9.8.data/platlib/eqc_models/ml/clustering.py +323 -0
  33. eqc_models-0.9.8.data/platlib/eqc_models/ml/clusteringbase.py +112 -0
  34. eqc_models-0.9.8.data/platlib/eqc_models/ml/decomposition.py +363 -0
  35. eqc_models-0.9.8.data/platlib/eqc_models/ml/forecast.py +255 -0
  36. eqc_models-0.9.8.data/platlib/eqc_models/ml/forecastbase.py +139 -0
  37. eqc_models-0.9.8.data/platlib/eqc_models/ml/regressor.py +220 -0
  38. eqc_models-0.9.8.data/platlib/eqc_models/ml/regressorbase.py +97 -0
  39. eqc_models-0.9.8.data/platlib/eqc_models/ml/reservoir.py +106 -0
  40. eqc_models-0.9.8.data/platlib/eqc_models/sequence/__init__.py +5 -0
  41. eqc_models-0.9.8.data/platlib/eqc_models/sequence/tsp.py +217 -0
  42. eqc_models-0.9.8.data/platlib/eqc_models/solvers/__init__.py +12 -0
  43. eqc_models-0.9.8.data/platlib/eqc_models/solvers/qciclient.py +707 -0
  44. eqc_models-0.9.8.data/platlib/eqc_models/utilities/__init__.py +6 -0
  45. eqc_models-0.9.8.data/platlib/eqc_models/utilities/fileio.py +38 -0
  46. eqc_models-0.9.8.data/platlib/eqc_models/utilities/polynomial.py +137 -0
  47. eqc_models-0.9.8.data/platlib/eqc_models/utilities/qplib.py +375 -0
  48. eqc_models-0.9.8.dist-info/LICENSE.txt +202 -0
  49. eqc_models-0.9.8.dist-info/METADATA +139 -0
  50. eqc_models-0.9.8.dist-info/RECORD +52 -0
  51. eqc_models-0.9.8.dist-info/WHEEL +5 -0
  52. eqc_models-0.9.8.dist-info/top_level.txt +2 -0
@@ -0,0 +1,6 @@
1
+ # (C) Quantum Computing Inc., 2024.
2
+ from .polynomial import evaluate_polynomial, convert_hamiltonian_to_polynomial
3
+ from .fileio import read_coefficient_file, read_config_file, read_index_file
4
+
5
+ __all__ = ["evaluate_polynomial",
6
+ "read_coefficient_file", "read_index_file", "read_config_file", "convert_hamiltonian_to_polynomial"]
@@ -0,0 +1,38 @@
1
+ # (C) Quantum Computing Inc., 2024.
2
+ import csv
3
+
4
+ def read_config_file(filename):
5
+ config = {}
6
+ with open(filename, 'r') as file:
7
+ for line in file:
8
+ line = line.strip()
9
+ if line and '=' in line:
10
+ key, value = line.split('=', 1)
11
+ config[key.strip()] = value.strip()
12
+ return config
13
+
14
+ def read_coefficient_file(filename):
15
+ with open(filename, 'r') as file:
16
+ reader = csv.reader(file)
17
+ coefficients = [float(x) for x, in reader]
18
+ return coefficients
19
+
20
+ def read_index_file(filename):
21
+ indices = []
22
+ with open(filename, 'r') as file:
23
+ reader = csv.reader(file)
24
+ for item in reader:
25
+ indices.append([int(x.strip()) for x in item])
26
+ return indices
27
+
28
+ def write_coefficient_file(filename, coefficients):
29
+ with open(filename, "w") as fp:
30
+ for val in coefficients:
31
+ fp.write(f"{val}\n")
32
+
33
+ def write_indices_file(filename, indices):
34
+ with open(filename, "w") as fp:
35
+ writer = csv.writer(fp)
36
+ for row in indices:
37
+ writer.writerow(row)
38
+
@@ -0,0 +1,137 @@
1
+ # (C) Quantum Computing Inc., 2024.
2
+ import itertools
3
+
4
+
5
+ def evaluate_polynomial(terms, solution):
6
+ val = 0
7
+ # print(solution)
8
+ for k, coeff in terms.items():
9
+ term = coeff
10
+ for idx in k:
11
+ if idx > 0:
12
+ idx -= 1
13
+ term *= solution[idx]
14
+ # if term != 0:
15
+ # print(k, term)
16
+ val += term
17
+ return val
18
+
19
+
20
+ def convert_hamiltonian_to_polynomial(
21
+ A,
22
+ B,
23
+ C,
24
+ D,
25
+ num_vars,
26
+ ):
27
+ """Converts a hamiltonian of up to fourth order to a polynomial.
28
+
29
+ D_{ijkl} x_i x_j x_k x_l + C_{ijk} x_i x_j x_k + B_{ij} x_i x_j
30
+ + A_i x_i
31
+
32
+ Input:
33
+
34
+
35
+ A: First order hamiltonian.
36
+ B: Second order hamiltonian.
37
+ C: Third order hamiltonian.
38
+ D: Fourth order hamiltonian.
39
+ num_vars: Number of variables.
40
+
41
+ Output:
42
+
43
+ polynomial_indices, polynomila_coefs: Indices and coefficients of
44
+ polynomial that respresents the hamiltonian.
45
+
46
+ """
47
+
48
+ assert num_vars >= 1, "Invalid number of variables <%d>!" % num_vars
49
+
50
+ if D is not None:
51
+ assert D.shape[0] == num_vars, "Inconsistent dimensions!"
52
+ assert D.shape[1] == num_vars, "Inconsistent dimensions!"
53
+ assert D.shape[2] == num_vars, "Inconsistent dimensions!"
54
+ assert D.shape[3] == num_vars, "Inconsistent dimensions!"
55
+ poly_order = 4
56
+ elif C is not None:
57
+ assert C.shape[0] == num_vars, "Inconsistent dimensions!"
58
+ assert C.shape[1] == num_vars, "Inconsistent dimensions!"
59
+ assert C.shape[2] == num_vars, "Inconsistent dimensions!"
60
+ poly_order = 3
61
+ elif B is not None:
62
+ assert B.shape[0] == num_vars, "Inconsistent dimensions!"
63
+ assert B.shape[1] == num_vars, "Inconsistent dimensions!"
64
+ poly_order = 2
65
+ elif A is not None:
66
+ assert A.shape[0] == num_vars, "Inconsistent dimensions!"
67
+ poly_order = 1
68
+ else:
69
+ assert False, "No hamiltonian provided!"
70
+
71
+ poly_indices = []
72
+ poly_coefs = []
73
+
74
+ if A is not None:
75
+ for i in range(num_vars):
76
+ coef_val = A[i]
77
+
78
+ if coef_val != 0:
79
+ poly_coefs.append(coef_val)
80
+ poly_indices.append([0] * (poly_order - 1) + [i + 1])
81
+
82
+ if B is not None:
83
+ for i in range(num_vars):
84
+ for j in range(i, num_vars):
85
+ if i == j:
86
+ coef_val = B[i][i]
87
+ else:
88
+ coef_val = B[i][j] + B[j][i]
89
+
90
+ if coef_val != 0:
91
+ poly_coefs.append(coef_val)
92
+ poly_indices.append(
93
+ [0] * (poly_order - 2) + [i + 1, j + 1]
94
+ )
95
+
96
+ if C is not None:
97
+ for i in range(num_vars):
98
+ for j in range(i, num_vars):
99
+ for k in range(j, num_vars):
100
+ unique_perms = [
101
+ list(item)
102
+ for item in set(itertools.permutations([i, j, k]))
103
+ ]
104
+ coef_val = 0.0
105
+ for item in unique_perms:
106
+ coef_val += C[item[0]][item[1]][item[2]]
107
+
108
+ if coef_val != 0:
109
+ poly_coefs.append(coef_val)
110
+ poly_indices.append(
111
+ [0] * (poly_order - 3) + [i + 1, j + 1, k + 1]
112
+ )
113
+
114
+ if D is not None:
115
+ for i in range(num_vars):
116
+ for j in range(i, num_vars):
117
+ for k in range(j, num_vars):
118
+ for l in range(k, num_vars):
119
+ unique_perms = [
120
+ list(item)
121
+ for item in set(
122
+ itertools.permutations([i, j, k, l])
123
+ )
124
+ ]
125
+ coef_val = 0.0
126
+ for item in unique_perms:
127
+ coef_val += D[item[0]][item[1]][item[2]][
128
+ item[3]
129
+ ]
130
+
131
+ if coef_val != 0:
132
+ poly_coefs.append(coef_val)
133
+ poly_indices.append(
134
+ [i + 1, j + 1, k + 1, l + 1]
135
+ )
136
+
137
+ return poly_indices, poly_coefs
@@ -0,0 +1,375 @@
1
+ # (C) Quantum Computing Inc., 2024.
2
+ """
3
+ Read the file format from QPLIB (https://doi.org/10.1007/s12532-018-0147-4)
4
+
5
+ The "problem type" is a string of three characters.
6
+
7
+ The first character indicates the type of objective function used. It must be one of the following:
8
+
9
+ L a linear objective function
10
+ D a convex quadratic objective function whose Hessian is a diagonal matrix
11
+ C a convex quadratic objective function
12
+ Q a quadratic objective function whose Hessian may be indefinite
13
+
14
+ The second character indicates the types of variables that are present. It must be one of the following:
15
+
16
+ C all the variables are continuous
17
+ B all the variables are binary (0-1)
18
+ M the variables are a mix of continuous and binary
19
+ I all the variables are integer
20
+ G the variables are a mix of continuous, binary and integer
21
+
22
+ The third character indicates the type of the (most extreme) constraint function used; other constraints may be of a lesser type. It must be one of the following:
23
+
24
+ N there are no constraints
25
+ B some of the variables lie between lower and upper bounds (box constraints)
26
+ L the constraint functions are linear
27
+ D the constraint functions are convex quadratics with diagonal Hessians
28
+ C the constraint functions are convex quadratics
29
+ Q the constraint functions are quadratics whose Hessians may be indefinite
30
+
31
+ Thus for continuous problems, we would have
32
+
33
+ LCL a linear program
34
+ LCC or LCQ a linear program with quadratic constraints
35
+ CCB or QCB a bound-constrained quadratic program
36
+ CCL or QCL a quadratic program
37
+ CCC or CCQ or a quadratic program with quadratic constraints
38
+ QCC or QCQ
39
+
40
+ """
41
+
42
+ # "problem name" (character string)
43
+ # "problem type" (character string)
44
+ # "problem sense" i.e. one of the words minimize or maximize (character string) (Y)
45
+ # "number of variables" (integer)
46
+ # "number of general linear constraints" (integer) [1]
47
+ # "number of nonzeros in lower triangle of H" (integer) [2]
48
+ # "row" "column" "value" for each entry of H (if any), one triple on each line
49
+ # "default value for entries in g"
50
+ # "number of non-default entries in g"
51
+ # "index" "value" for each non-default term in g (if any), one pair per line (Y)
52
+ # "value of f"
53
+ # "number of nonzeros in lower triangles of H_c" (integer) [1,3]
54
+ # "constraint" "row" "column" "value" for each entry of H_c (if any),
55
+ # one quadruple on each line
56
+ # "number of nonzeros in A" (integer) [1]
57
+ # "row" "column" "value" for each entry of A (if any), one triple on each line
58
+ # "value for infinity" for bounds - any bound greater than or equal to this
59
+ # in absolute value is infinite
60
+ # "default value for entries in c_l" [1]
61
+ # "number of non-default entries in c_l" (integer) [1]
62
+ # "index" "value" for each non-default term in c_l (if any), one pair per line
63
+ # "default value for entries in c_u" [1]
64
+ # "number of non-default entries in c_u" (integer) [1]
65
+ # "index" "value" for each non-default term in c_u (if any), one pair per line
66
+ # "default value for entries in x_l" [4]
67
+ # "number of non-default entries in x_l" (integer) [4]
68
+ # "index" "value" for each non-default term in x_l (if any), one pair per line [4]
69
+ # "default value for entries in x_u" [4]
70
+ # "number of non-default entries in x_u" (integer) [4]
71
+ # "index" "value" for each non-default term in x_u (if any), one pair per line [4]
72
+ # "default variable type" (0 for continuous variable, 1 for integer) [5]
73
+ # "number of non-default variables" (integer) [5]
74
+ # "index" "value" for each non-default variable type (if any), one pair per line
75
+ # "default value for starting value for variables x"
76
+ # "number of non-default starting entries in x" (integer)
77
+ # "index" "value" for each non-default term in x (if any), one pair per line
78
+ # "default value for starting value for Lagrange multipliers y for constraints"[1]
79
+ # "number of non-default starting entries in y" (integer) [1]
80
+ # "index" "value" for each non-default term in y (if any), one pair per line
81
+ # "default value for starting value for dual variables z for simple bounds"
82
+ # "number of non-default starting entries in z" (integer)
83
+ # "index" "value" for each non-default term in z (if any), one pair per line
84
+ # "number of non-default names of variables" - default for variable i is "i"
85
+ # "index" "name" for each non-default name for variable x_i with index i (if any)
86
+ # "number of non-default names of constraints" - default for constraint i is "i"
87
+ # "index" "name" for each non-default name for constraint with index i (if any)
88
+
89
+
90
+ from typing import Dict, List, TextIO, Tuple
91
+ import logging
92
+ import numpy as np
93
+ from eqc_models.base.quadratic import QuadraticModel, ConstrainedQuadraticModel
94
+ logger = logging.getLogger(name=__name__)
95
+ class QBBModel(QuadraticModel):
96
+ """
97
+ QBB - Quadratic objective, binary variable type, unconstrained
98
+
99
+ This model type is the same as a QUBO model, but the linear portion is
100
+ specified separately, instead of in the diagonal.
101
+
102
+ Parameters
103
+ -------------
104
+
105
+ :C: np.ndarray - linear portion of the objective
106
+ :J: np.ndarray - quadratic portion of the objective
107
+
108
+ """
109
+
110
+ class QGLModel(ConstrainedQuadraticModel):
111
+ """
112
+ QGL - Quadratic objective, General variable type, Linear constraints
113
+ Handles QCL, QIL, QBL, QML problems
114
+
115
+ Parameters
116
+ ------------
117
+
118
+ :C: np.ndarray - linear portion of the objective
119
+ :J: np.ndarray - quadratic portion of the objective
120
+ :A: np.ndarray - left hand side of the linear constraints
121
+ :b: np.ndarray - right hand side of the linear constraints
122
+
123
+ """
124
+
125
+ def read_line(fp : TextIO) -> Dict:
126
+ line = fp.readline()
127
+ line = line.strip()
128
+ line = line.replace("\t", " ")
129
+ values = line.split(" ")
130
+ values = [v for v in values if v != ""]
131
+ if "#" in values:
132
+ values = values[:values.index("#")]
133
+ if "%" in values:
134
+ values = values[:values.index("%")]
135
+ if "!" in values:
136
+ values = values[:values.index("!")]
137
+ for i in range(len(values)):
138
+ try:
139
+ v1 = float(values[i])
140
+ except ValueError:
141
+ v1 = ""
142
+ try:
143
+ v2 = int(values[i])
144
+ except:
145
+ v2 = None
146
+ if v2 == v1:
147
+ values[i] = v2
148
+ elif v1 != "":
149
+ values[i] = v1
150
+ return values
151
+
152
+ def process_file(fp, DTYPE=np.float32):
153
+ """
154
+ Read the file line by line, saving the parts objective (C, Q) and constraints (A, b)
155
+ """
156
+ # read the problem name
157
+ name = read_line(fp)[0]
158
+ # problem type QML, QCL, etc
159
+ problem_type = read_line(fp)[0]
160
+ # type: minimize/maximize
161
+ sense = read_line(fp)[0].lower()
162
+ if problem_type not in ("QCL", "QIL", "QBL", "QML", "QGL", "QBB"):
163
+ raise ValueError(f"Problem type {problem_type} is not supported")
164
+ if sense not in ("minimize", "maximize"):
165
+ raise ValueError(f"Unknown problem sense: {sense}")
166
+ # variable count
167
+ num_variables = read_line(fp)[0]
168
+ if problem_type[2] not in ("B", "N"):
169
+ # number of constaints
170
+ num_linear_constraints = read_line(fp)[0]
171
+ else:
172
+ num_linear_constraints = 0
173
+ # number of quadratic terms in objective
174
+ if problem_type[0] != "L":
175
+ num_Q_entries = read_line(fp)[0]
176
+ J = np.zeros((num_variables, num_variables), dtype=DTYPE)
177
+ for i in range(num_Q_entries):
178
+ values = read_line(fp)
179
+ i, j, val = values
180
+ # Q.append({"i": i, "j": j, "val": val})
181
+ # if i==j:
182
+ val /= 2
183
+ J[i-1, j-1] = val
184
+ # J is the lower triangular portion of the Hessian
185
+ # print(J)
186
+ # print(np.tril(J, -1).T)
187
+ # J += np.tril(J, -1).T
188
+ # print(J)
189
+ J += J.T
190
+ J /= 2
191
+ else:
192
+ num_Q_entries = 0
193
+ J = None
194
+ # default for linear terms
195
+ default_linear = read_line(fp)[0]
196
+ # number of non default linear terms
197
+ non_default_entries = read_line(fp)[0]
198
+ C = default_linear * np.ones((num_variables,1), dtype=DTYPE)
199
+ for i in range(non_default_entries):
200
+ i, val = read_line(fp)
201
+ # C.append({"i": i, "val": val})
202
+ C[i-1, 0] = val
203
+ # objective constant
204
+ obj_const = read_line(fp)[0]
205
+ # number of linear terms in constraints
206
+ num_A_entries = read_line(fp)[0]
207
+ if np.isinf(num_A_entries):
208
+ num_A_entries = 0
209
+ A = np.zeros((num_linear_constraints, num_variables), dtype=DTYPE)
210
+ for idx in range(num_A_entries):
211
+ i, j, val = read_line(fp)[:3]
212
+ try:
213
+ A[i-1, j-1] = val
214
+ except IndexError:
215
+ raise IndexError(f"Incorrect index {(i,j)} for shape {A.shape}")
216
+ infty = read_line(fp)[0]
217
+ # default lhs value
218
+ # QPLIB uses LHS values to indicate constraint type: EQ or LE
219
+ default_cons = read_line(fp)[0]
220
+ # LHS value of 1 means EQ constraint
221
+ # -1 means LE constraint
222
+ num_non_default_cons = int(read_line(fp)[0])
223
+ cons = default_cons * np.ones((num_linear_constraints, 1), dtype=DTYPE)
224
+ for idx in range(num_non_default_cons):
225
+ i, val = read_line(fp)[:2]
226
+ cons[i-1, 0] = val
227
+ cons = ["EQ" if c == 1 else "LE" for c in cons]
228
+ # default rhs value
229
+ default_rhs = read_line(fp)[0]
230
+ # number of non-default right hand sides
231
+ num_rhs_entries = int(read_line(fp)[0])
232
+ b = default_rhs * np.ones((num_linear_constraints, 1), dtype=DTYPE)
233
+ for idx in range(num_rhs_entries):
234
+ i, val = read_line(fp)[:2]
235
+ b[i-1, 0] = val
236
+ # default lower bound
237
+ # variable upper bound
238
+ if problem_type[1] != "B":
239
+ var_lb = read_line(fp)[0]
240
+ # number of non-default lower bounds
241
+ num_non_default_lb = int(read_line(fp)[0])
242
+ lb = var_lb * np.ones((num_variables,1), dtype=DTYPE)
243
+ for idx in range(num_non_default_lb):
244
+ i, val = read_line(fp)[:2]
245
+ lb[i-1, 0] = val
246
+ var_ub = read_line(fp)[0]
247
+ # number of non-default upper bounds
248
+ num_non_default_ub = int(read_line(fp)[0])
249
+ ub = var_ub * np.ones((num_variables,1), dtype=DTYPE)
250
+ for idx in range(num_non_default_ub):
251
+ i, val = read_line(fp)[:2]
252
+ ub[i-1, 0] = val
253
+ else:
254
+ # binary variables
255
+ lb = np.zeros((num_variables,1), dtype=DTYPE)
256
+ var_ub = 1
257
+ ub = var_ub * np.ones((num_variables,1), dtype=DTYPE)
258
+ # get variable types
259
+ variable_types = {0: "REAL", 1: "INT"}
260
+ if problem_type[1] not in ("C", "B", "I"):
261
+ default_variable_type = read_line(fp)[0]
262
+ # number of non-default variable types
263
+ num_non_default_types = int(read_line(fp)[0])
264
+ types = [variable_types[default_variable_type] for i in range(num_variables)]
265
+ for idx in range(num_non_default_types):
266
+ i, val = read_line(fp)[:2]
267
+ val = int(val)
268
+ types[i-1] = variable_types[val]
269
+ elif problem_type[1] == "C":
270
+ default_variable_type = 0
271
+ types = [variable_types[default_variable_type] for i in range(num_variables)]
272
+ else:
273
+ default_variable_type = 1
274
+ types = [variable_types[default_variable_type] for i in range(num_variables)]
275
+ if problem_type[2] not in ["B", "N"]:
276
+ # default primal value in starting point
277
+ default_primal_value = read_line(fp)[0]
278
+ # number of non default primal values
279
+ num_non_default_primal_values = read_line(fp)[0]
280
+ if types == ["INT" for j in range(num_variables)]:
281
+ primal_dtype = np.int32
282
+ else:
283
+ primal_dtype = DTYPE
284
+ starting_primal = default_primal_value * np.ones((num_variables, 1), dtype=primal_dtype)
285
+ # read non-default primals
286
+ for idx in range(num_non_default_primal_values):
287
+ i, val = read_line(fp)[0]
288
+ starting_primal[i-1, 0] = val
289
+ # default constraint dual value in starting point
290
+ default_constraint_dual = read_line(fp)[0]
291
+ # number of non default constraint dual values
292
+ num_non_default_dual_values = read_line(fp)[0]
293
+ starting_constraint_dual = default_constraint_dual * np.ones(
294
+ (num_linear_constraints, 1), dtype=DTYPE)
295
+ # read non-default constraint duals
296
+ for idx in range(num_non_default_dual_values):
297
+ i, val = read_line(fp)[:2]
298
+ starting_constraint_dual[i-1, 0] = val
299
+ # default variable bound dual value in starting point
300
+ default_variable_bound_dual = read_line(fp)[0]
301
+ # number of non default variable bound dual values
302
+ num_non_default_bound_dual_values = read_line(fp)[0]
303
+ starting_bound_dual = default_variable_bound_dual * np.ones(
304
+ (num_variables, 1), dtype=DTYPE
305
+ )
306
+ # read non-default variable bound dual values
307
+ for idx in range(num_non_default_bound_dual_values):
308
+ i, val = read_line(fp)[:2]
309
+ starting_bound_dual[i-1, 0] = val
310
+ variable_names = [f"x{j}" for j in range(num_variables)]
311
+ # read variable names
312
+ try:
313
+ item = read_line(fp)
314
+ num_non_default_variable_names = item[0]
315
+ except IndexError:
316
+ print(item)
317
+ raise
318
+ for i in range(num_non_default_variable_names):
319
+ i, val = read_line(fp)[:2]
320
+ variable_names[i-1] = val
321
+ constraint_names = [f"c{i}" for i in range(num_linear_constraints)]
322
+ # read constraint names
323
+ num_non_default_constraint_names = read_line(fp)[0]
324
+ for i in range(num_non_default_constraint_names):
325
+ i, val = read_line(fp)[:2]
326
+ constraint_names[i-1] = val
327
+ del fp
328
+ return locals()
329
+
330
+ def file_to_model(fp : TextIO, DTYPE=np.float32) -> QGLModel:
331
+
332
+ parts = process_file(fp, DTYPE)
333
+ problem_type = parts["problem_type"]
334
+ if parts["sense"] == "maximize":
335
+ parts["C"] *= -1
336
+ parts["J"] *= -1
337
+ if problem_type == "QBB":
338
+ # QUBO
339
+ model = QBBModel(parts["C"], parts["J"])
340
+ else:
341
+ model = QGLModel(parts["C"], parts["J"], parts["A"], parts["b"])
342
+ if not np.isinf(parts["ub"]).any():
343
+ model.upper_bound = np.squeeze(parts["ub"].astype(np.int64))
344
+ else:
345
+ upper_bounds = np.array(parts["ub"])
346
+ upper_bounds[upper_bounds==np.inf] = 10000 # max for any value in Dirac-3
347
+ n = parts["C"].shape[0]
348
+ model.upper_bound = upper_bounds.reshape((n,))
349
+ return model
350
+
351
+ def file_to_polynomial(fp : TextIO, DTYPE=np.float32, penalty_multiplier=1) -> Tuple[List, List]:
352
+ """
353
+ Create a pair of lists describing a polynomial that
354
+ represents the file contained in the qplib-formatted file
355
+ descriptor fp. Sets a guess for the sum constraint when constructing
356
+ the model, but it has no effect on the polynomial file output.
357
+
358
+ Parameters
359
+ :fp: File descriptor for qplib-formatted file
360
+ :DTYPE: Default numeric datatype for non-integer numeric values
361
+
362
+ Returns
363
+ :coefficients:, :indices:
364
+ """
365
+
366
+ parts = process_file(fp, DTYPE)
367
+ sum_constraint = float(np.sum(parts["b"]))
368
+ model = QGLModel(parts["C"], parts["J"], parts["A"], parts["b"])
369
+ model.penalty_multiplier = penalty_multiplier
370
+ model.upper_bound = np.array([sum_constraint for i in range(model.linear_objective.shape[0])])
371
+ logger.info("Dynamic Range: %f", model.dynamic_range)
372
+ polynomial = model.polynomial
373
+ coefficients = polynomial.coefficients
374
+ indices = polynomial.indices
375
+ return coefficients, indices, sum_constraint