Closed sirgeorgesawcon closed 5 months ago
I am following the legacy CutQC first tutorial , and I am encountering this issue if I use a different circuit from the one mentioned in the tutorial.
Thanks @sirgeorgesawcon , will try to reproduce
@sirgeorgesawcon , we have been seeing several different problems with cutqc. It is legacy software, and we are trying to migrate users to the newer wire cutting functionality.
We also have an implementation of an automat cut-finder which supports both gates and wire cuts in a branch here, which should be available in the upcoming release.
I wonder if this new package suits your needs.
Hi @caleb-johnson
We also have an implementation of an automat cut-finder which supports both gates and wire cuts in a branch here, which should be available in the upcoming release.
Is this version the one that does the gate and wire cut simultaneously in a given quantum circuit? Based on this work.
Is this version the one that does the gate and wire cut simultaneously in a given quantum circuit? Based on this work.
Yes, our newer cutting
package can do both gate and wire cutting. They both use quasi-probability decompositions to decompose 2-qubit gates and wires into local operations. We drew from the references at the bottom of this page during implementation.
In addition to the tutorial(s) I linked above, we have an automatic cut-finder coming soon, which will help users find cut locations to most efficiently partition their circuit. An example of how it will work can be found in a branch here.
Please let us know if you try out the new cutting
package! :)
I tried the cutting
package, and from what I see it works with Qiskit 0.45 and less, and doesn't with Qiskit 1.0, but I saw other PR and saw that people are working on it too. Sometimes I get the error of divide by 0
using some random circuit and some random choice of observables, but it still cuts the circuit nevertheless.
But the result from uncut circuit and the one we cut if much different,
For instance
import numpy as np
from qiskit.circuit.random import random_circuit
'''
This function generates a random quantum circuit, of given size and width, and deopth,
and also the max entangled operation
'''
from qiskit.quantum_info import PauliList
circuit = random_circuit(8, 5, max_operands=2, seed=1242)
observables = PauliList(["IZIIIIII", "IIIIZIII", "IIIIIIIZ"])
circuit.draw("mpl",style='iqx', scale=0.8)
makes this circuit
and giving it these parameters to look for a cut
from circuit_knitting.cutting import find_cuts
# specify the settings
optimization_settings = {"rand_seed": 42}
# specify the constraints
device_constraints = {"num_QPUs": 2, "qubits_per_QPU": 5}
# do the cut
cut_circuit = find_cuts(circuit, optimization_settings, device_constraints)
# draw the cut circuit
cut_circuit.draw("mpl",style='iqx', scale=0.8)
It draws the following
and after adding ancilla
It is a nice cut, since the sampling overhead is around 58.
But, the moment I reconstruct the circuit
from qiskit_aer.primitives import Sampler
# Set up a Qiskit Aer Sampler primitive for each circuit partition
samplers = {
label: Sampler(run_options={"shots": 2**12}) for label in subexperiments.keys()
}
# Retrieve results from each partition's subexperiments
results = {
label: sampler.run(subexperiments[label]).result()
for label, sampler in samplers.items()
}
and compare it:
from circuit_knitting.cutting import reconstruct_expectation_values
reconstructed_expvals = reconstruct_expectation_values(
results,
coefficients,
subobservables,
)
from qiskit_aer.primitives import Estimator
estimator = Estimator(run_options={"shots": None}, approximation=True)
exact_expvals = (
estimator.run([qc] * len(observables), list(observables)).result().values
)
print(
f"Reconstructed expectation values: {[np.round(reconstructed_expvals[i], 8) for i in range(len(exact_expvals))]}"
)
print(
f"Exact expectation values: {[np.round(exact_expvals[i], 8) for i in range(len(exact_expvals))]}"
)
print(
f"Errors in estimation: {[np.round(reconstructed_expvals[i]-exact_expvals[i], 8) for i in range(len(exact_expvals))]}"
)
print(
f"Relative errors in estimation: {[np.round((reconstructed_expvals[i]-exact_expvals[i]) / exact_expvals[i], 8) for i in range(len(exact_expvals))]}"
)
We get
Reconstructed expectation values: [-0.56650392, 0.6264455, -0.86957383]
Exact expectation values: [0.1948505, 0.47016598, 0.66808262]
Errors in estimation: [-0.76135442, 0.15627952, -1.53765645]
Relative errors in estimation: [-3.90737728, 0.33239223, -2.30159624]
There's a big gap between the uncut and cut values. It might be because I'm doing something wrong during the reconstruction part of the circuit, but I can't figure it out.
Basically I want to contribute a tutorial on solving a big MaxCut problem with QAOA, with using both gate and wire cut, and that's what I'm currently working on. But the initial results don't match, for a random circuit.
I am following the legacy CutQC first tutorial , and I am encountering this issue if I use a different circuit from the one mentioned in the tutorial.
How to recreate the error?
I'm using the following circuit
Then I find the cut automatically, using these set of parameters:
It gives me two subcircuits:
Then When I try to run it using:
and use the
evaluate_subcircuits
functionIt gives me the error:
IndexError: string index out of range
If I use the circuit in tutorial, it works out smoothly.
System Info
Python : 3.10.11 Qiskit : 0.46.0 qiskit_ibm_runtime : 0.19.1 qiskit_aer : 0.13.3