jpmorganchase / qokit Goto Github PK
View Code? Open in Web Editor NEWQOKit
Home Page: https://www.jpmorgan.com/technology/applied-research
License: Apache License 2.0
QOKit
Home Page: https://www.jpmorgan.com/technology/applied-research
License: Apache License 2.0
It has been reported that the MPI simulators are broken. This issue is to document the issues with the MPI simulators and to add local tests for them.
If the input specifying the problem for get_qaoa_maxcut_objective
is a network graph G
, then terms should be generated and the GPU precomputation from terms called.
I'm using Windows 10. When installing qokit using a conda environment with Python 3.11, pytest fails with 12 errors. When installing qokit using a conda environment with Python 3.9, pytest passes 99 tests and fails 1 test:
tests/test_labs.py::test_gate_optimized_terms_greedy - ValueError: high is out of bounds for int32
Note: I am running 64 bit python in both scenarios.
In you example "Simulation of QAOA applied to a general problem", you gave an example specified by 'terms' below:
N = 4
np.random.seed(10)
terms = [(np.random.normal(), spin_pair) for spin_pair in combinations(range(N), r=2)]
I wonder how to get the objective function in order to optimize this general Hamiltonian. Many thanks.
In certain conditions, when precomputed_costs
is not provided by the user, qokit would calculate it with CPU-version functions outside of the simulator. This is intractable when the number of qubits is high. Instead, precomputed_costs
should be either user-provided or calculated in fur with the user-specified backend, whenever possible. The explicit retrieving precomputed_costs
from the simulator and re-passing-in when calling the simulator objective functions should also be avoided, which, when the backend is GPU, can eliminate an unnecessary copy of the large energy vector in the CPU memory and reduce communication time.
#34 needs to be addressed to correctly implement this. Constraint-related values (e.g. portfolio optimization overlap) will be tricky for the simulator to calculate and have to be done outside of the simulator for now.
Currently, there are two arguments related to precomputed energies in get_qaoa_objective()
. precomputed_diagonal_hamiltonian
is passed into the simulator but not used for get-objective functions after the simulation, except when precomputed_costs
is None
. However, judging from problem-specific get-objective functions, this exception is never the case, and even if so, it would produce incorrect results. Having two similar arguments leads to ambiguity and the duplication of the energy vector, whose size is exponential in the number of qubits.
At a high level, the workflow we are hoping to enable with QOKit is as follows:
The same flow should work for other problems (portfolio optimization, LABS, ...)
However, it is triggered and fails in #49
I have been trying to use the QOKit simulator for larger instances but before that I wanted to verify it works for some trivial small ones.
I'd love some insight into if I'm doing something wrong -- thank you in advance ๐
I have created a basic 2-regular
or ring graph
The solution for the two subsets are trivial:
However; when I run the code (see below) -- brute-force output is incorrect.
Pls let me know if I'm implementing this wrong?
from qokit.utils import brute_force
from qokit.qaoa_objective_maxcut import get_qaoa_maxcut_objective
from qokit.qaoa_circuit_maxcut import get_parameterized_qaoa_circuit
import gurobipy as gp
from gurobipy import GRB
# Define # of Layers
N_LAYERS = 20
# Generate a random 2-regular graph
N = 6
d = 2
seed = 1
G = nx.random_regular_graph(d,N,seed=seed)
# Build QC Circuit
qc = get_parameterized_qaoa_circuit(G, N_LAYERS)
qaoa_obj = get_qaoa_maxcut_objective(N, N_LAYERS, G)
brute_force_sol = brute_force(qaoa_obj, N, minimize=True)
print(brute_force_sol)
>>> (-1.091045519270739, array([1, 1, 0, 1, 1, 0]))
Here is a plot:
I also validated with Gurobi and it can produce the correct solution:
import gurobipy as gp
from gurobipy import GRB
for (u, v) in G.edges():
G.edges[u, v]['weight'] = 1 # Set to 1 or some other weight if needed
# Create a new model
m = gp.Model("max_cut")
x = m.addVars(G.nodes(), vtype=GRB.BINARY, name="x")
m.setObjective(gp.quicksum(G[u][v]['weight'] * (x[u] + x[v] - 2 * x[u] * x[v]) for u, v in G.edges()), GRB.MAXIMIZE)
m.optimize()
if m.status == GRB.OPTIMAL:
solution = m.getAttr('x', x)
print("Solution:")
for v in solution:
print(f"Vertex {v}: {int(solution[v])}")
else:
print("No optimal solution found.")
The package qokit
depends on qiskit-ibmq-provider (<1,>=0.20.2)
https://www.wheelodex.org/projects/qokit/ which is not maintained any more and it was replaced by qiskit-ibm-runtime
.
See the migration guide here: https://docs.quantum.ibm.com/api/migration-guides/qiskit-runtime
"tests passing" badge does not render in public version as it points to the wrong repo
The problem is caused by line 502 in labs.py.
Replacing line 502 with seed = seed if seed else np.random.randint(np.iinfo(np.int32).max)
fixes the issue.
@alex124585, would you mind submitting a PR with the above change?
Thank you!
See error below.
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[2], line 4
2 p = 1
3 gamma, beta = parameter_utils.get_best_known_parameters_for_LABS_wrt_overlap_for_p(N, p)
----> 4 terms = get_gate_optimized_terms_greedy(N) # indices of Pauli Zs
File ~\Dropbox\ANL\qaoaPortfolioOptimization\test\QOKit\qokit\labs.py:502, in get_gate_optimized_terms_greedy(N, number_of_gate_zones, seed)
498 two_body.append((i, i + 2 * k))
500 circuit = []
--> 502 seed = seed if seed else np.random.randint(sys.maxsize)
503 print(f"seed: {seed}")
504 rng = np.random.default_rng(seed)
File mtrand.pyx:746, in numpy.random.mtrand.RandomState.randint()
File _bounded_integers.pyx:1336, in numpy.random._bounded_integers._rand_int32()
ValueError: high is out of bounds for int32
The sign problem of calling get_qaoa_maxcut_objective
when passing the precomputed energy or Graph.
At least need a instruction of how to get the correct overlap by calling get_qaoa_maxcut_objective
Minimal reproducible example:
pip install git+https://github.com/jpmorganchase/QOKit
from qokit.parameter_utils import get_fixed_gamma_beta
get_fixed_gamma_beta(3, 1)
causes
File "<stdin>", line 1, in <module>
File "/home/hao/.pyenv/versions/test/lib/python3.10/site-packages/qokit/parameter_utils.py", line 234, in get_fixed_gamma_beta
df = pd.read_json(str(files("qokit.assets.maxcut_datasets").joinpath("fixed_angles_for_regular_graphs.json")), orient="index")
File "/home/hao/.pyenv/versions/test/lib/python3.10/site-packages/importlib_resources/_common.py", line 46, in wrapper
return func(anchor)
File "/home/hao/.pyenv/versions/test/lib/python3.10/site-packages/importlib_resources/_common.py", line 56, in files
return from_package(resolve(anchor))
File "/home/hao/.pyenv/versions/3.10.4/lib/python3.10/functools.py", line 889, in wrapper
return dispatch(args[0].__class__)(*args, **kw)
File "/home/hao/.pyenv/versions/test/lib/python3.10/site-packages/importlib_resources/_common.py", line 82, in _
return importlib.import_module(cand)
File "/home/hao/.pyenv/versions/3.10.4/lib/python3.10/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
File "<frozen importlib._bootstrap>", line 1004, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'qokit.assets.maxcut_datasets'
Installing by manually cloning to local does not have this issue.
Running pip install .
fails to build c simulator on OmniQ.
As an additional fix, Github actions should check that c simulator is built correctly
Is there an example where QOKit evaluates the LABS circuit instead of the statevector simulation?
In the qaoa_objective_labs
file:
QOKit/qokit/qaoa_objective_labs.py
Line 19 in 29e010c
I see that the circuit is imported, but I don't see where it is ever used/evaluated? Isn't this necessary for large N?
(I see QOKit has this implemented for portfolio optimization though.)
This happens, for example, when calling MPI simulator's get_probabilities()
which does self._comm.allgather(result.copy_to_host())
. If the vector is too large (e.g. 32 qubits), the following is raised:
File "mpi4py/MPI/Comm.pyx", line 1595, in mpi4py.MPI.Comm.allgather
File "mpi4py/MPI/msgpickle.pxi", line 862, in mpi4py.MPI.PyMPI_allgather
File "mpi4py/MPI/msgpickle.pxi", line 147, in mpi4py.MPI.pickle_dump
File "mpi4py/MPI/msgbuffer.pxi", line 50, in mpi4py.MPI.downcast
OverflowError: integer 34359738509 does not fit in 'int'
which is due to a legacy issue of mpi4py/pickle (see mpi4py/mpi4py#119) that is solved by mpi4py.util.pkl5
. It seems the switch to pkl5
can be realized by simply changing the current self._comm = MPI.COMM_WORLD
to pkl5.Intracomm(MPI.COMM_WORLD)
.
Currently, a very nice parameterization is used to test that QAOA objective for LABS is computed the same way for all simulators (see tests/test_objectives.py
).
However, for MaxCut there are two separate files that manually test only a small number of simulators (I believe, only "auto" and "qiskit"): tests/test_qaoa_objective_maxcut.py
and tests/test_maxcut.py
.
At the same time, parameterization for LABS is missing "qiskit" simulator. I suspect this lack of test coverage is what caused #28.
The request is to add parameterization to MaxCut tests along the lines of how LABS tests are parameterized in tests/test_objectives.py
and to add "qiskit" simulator to the tests for LABS objective.
I would also suggest the following minor refactoring:
tests/test_objectives.py
-> tests/test_qaoa_objective_labs.py
test_maxcut_obj
from tests/test_maxcut.py
to tests/test_qaoa_objective_maxcut.py
np.assaray
is invalid for Nvidia datatypes)Higher level considerations:
When overlap objective is requested from get_qaoa_maxcut_objective
, the default behavior is to return an incorrect number (1).
Specifically, the following code:
import networkx as nx
import numpy as np
from functools import partial
from qokit.maxcut import maxcut_obj, get_adjacency_matrix
from qokit.utils import precompute_energies
from qokit.parameter_utils import get_fixed_gamma_beta
from qokit.qaoa_objective_maxcut import get_qaoa_maxcut_objective
N = 8
d = 3
seed = 1
G = nx.random_regular_graph(d,N,seed=seed)
obj = partial(maxcut_obj, w=get_adjacency_matrix(G))
precomputed_energies = precompute_energies(obj, N)
for p in range(1, 12):
gamma, beta = get_fixed_gamma_beta(d, p)
f = get_qaoa_maxcut_objective(
N, p, precomputed_cuts=precomputed_energies, parameterization='gamma beta', objective='expectation and overlap'
)
e,o = f(gamma, beta)
print(f"Energy: {e:.2f}, Overlap: {o:.2f}")
Returns
Energy: 7.98, Overlap: 1.00
Energy: 8.74, Overlap: 1.00
Energy: 9.24, Overlap: 1.00
Energy: 9.55, Overlap: 1.00
Energy: 9.76, Overlap: 1.00
Energy: 9.85, Overlap: 1.00
Energy: 9.87, Overlap: 1.00
Energy: 9.87, Overlap: 1.00
Energy: 9.85, Overlap: 1.00
Energy: 9.86, Overlap: 1.00
Energy: 9.90, Overlap: 1.00
Note that the energy is computed correctly, but the overlap is not.
Desired behavior
get_qaoa_objective
should use the information in precomputed_energies
to populate bitstring_loc
(https://github.com/jpmorganchase/QOKit/blob/0281555bdf4c8ca0a645f010e26adb78ae7d6197/qokit/qaoa_objective.py#L189C25-L189C25) object by noticing that the optimal bitstrings are those that correspond to maximum entries in precomputed_energies
, i.e.
optimal_energy = np.max(precomputed_energies)
optimal_bitstrings_location = np.isclose(precomputed_energies, optimal_energy).astype(int)
Note that a bit more work is needed since optimal_bitstrings_location
does not actually give you the correct format for bitstring_loc
(I think?..).
Only move the following folders: qokit
, tests
, workflow and all the setup / workflow stuff.
Make sure the pipeline runs OK
Flip the order of gamma and beta in MaxCut circuit generation:
QOKit/qokit/qaoa_circuit_maxcut.py
Line 34 in 492b7d4
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.