Open msierras opened 1 month ago
Hello,
Unfortunately class RigettiQCSBackend(BackendV1)
does not yet provide an implementation for BackendV1.properties
.
If it works for your purposes, you can use our InstructionSetArchitecture
format to view available gate instructions and their fidelities with the python package https://pypi.org/project/qcs-sdk-python
import json
from pprint import pprint
from qcs_sdk.qpu.isa import get_instruction_set_architecture
# or Ankaa-2
isa = get_instruction_set_architecture("Ankaa-9Q-3")
# Since the `isa` object is implemented in Rust and only exposed with Python bindings,
# it can be tricky to use directly. I recommend starting with the regular `isa` object
# because it provides type annotations, but it can also be converted to a dictionary.
isa_dict = json.loads(isa.json())
# The InstructionSetArchitecture format is not dictionary-like,
# but it can be converted to one without much trouble.
instructions = {
instr["name"]: {
"-".join([str(node_id) for node_id in site["node_ids"]]): site["characteristics"]
for site in instr["sites"]
}
for instr in isa_dict["instructions"]
}
pprint(instructions)
The output will look something like the following. Note that an instruction is supported for each site listed, even if the characteristic array (fidelity observations) is empty. Gates here are named using https://pyquil-docs.rigetti.com/en/stable/apidocs/pyquil.gates.html conventions.
{'CZ': {},
'I': {'0': [],
'1': [],
'2': [],
'3': [],
'4': [],
'5': [],
'6': [],
'7': [],
'8': []},
'ISWAP': {'0-1': [{'error': 0.0009449805045511142,
'name': 'fISWAP',
'timestamp': '2024-07-24T13:06:01+00:00',
'value': 0.9954455807297032}],
'0-3': [{'error': 0.0030053209962795984,
'name': 'fISWAP',
'timestamp': '2024-07-24T13:09:31+00:00',
'value': 0.9781603324881208}],
'1-2': [{'error': 0.0009737267917803602,
'name': 'fISWAP',
'timestamp': '2024-07-24T13:11:10+00:00',
'value': 0.9973678168854982}],
'1-4': [{'error': 0.0014055023479609646,
'name': 'fISWAP',
'timestamp': '2024-07-24T13:12:49+00:00',
'value': 0.992258384177466}],
'2-5': [{'error': 0.0007988414794355134,
'name': 'fISWAP',
'timestamp': '2024-07-24T13:07:46+00:00',
'value': 0.9945278333839892}],
'3-4': [{'error': 0.001453483056545156,
'name': 'fISWAP',
'timestamp': '2024-07-24T13:17:48+00:00',
'value': 0.9863628974048516}],
'3-6': [{'error': 0.0010498116228042824,
'name': 'fISWAP',
'timestamp': '2024-07-24T13:11:10+00:00',
'value': 0.9898050642434976}],
'4-5': [{'error': 0.0007882449741001306,
'name': 'fISWAP',
'timestamp': '2024-07-24T13:16:10+00:00',
'value': 0.994730786573078}],
'4-7': [{'error': 0.0013304631366279076,
'name': 'fISWAP',
'timestamp': '2024-07-24T13:14:30+00:00',
'value': 0.9907659655240126}],
'5-8': [{'error': 0.005364489303655767,
'name': 'fISWAP',
'timestamp': '2024-07-24T13:06:01+00:00',
'value': 0.9717185565192816}],
'6-7': [{'error': 0.0008074640561527317,
'name': 'fISWAP',
'timestamp': '2024-07-24T13:07:44+00:00',
'value': 0.993929426547962}],
'7-8': [{'error': 0.006114513752365264,
'name': 'fISWAP',
'timestamp': '2024-07-24T13:09:30+00:00',
'value': 0.9726377114338104}]},
'MEASURE': {'0': [{'name': 'fRO',
'timestamp': '2024-07-24T14:10:31+00:00',
'value': 0.967}],
'1': [{'name': 'fRO',
'timestamp': '2024-07-24T14:10:31+00:00',
'value': 0.965}],
'2': [{'name': 'fRO',
'timestamp': '2024-07-24T14:10:31+00:00',
'value': 0.952}],
'3': [{'name': 'fRO',
'timestamp': '2024-07-24T14:10:31+00:00',
'value': 0.96}],
'4': [{'name': 'fRO',
'timestamp': '2024-07-24T14:10:31+00:00',
'value': 0.959}],
'5': [{'name': 'fRO',
'timestamp': '2024-07-24T14:10:32+00:00',
'value': 0.976}],
'6': [{'name': 'fRO',
'timestamp': '2024-07-24T14:10:32+00:00',
'value': 0.944}],
'7': [{'name': 'fRO',
'timestamp': '2024-07-24T14:10:32+00:00',
'value': 0.946}],
'8': [{'name': 'fRO',
'timestamp': '2024-07-24T14:10:32+00:00',
'value': 0.962}]},
'RX': {'0': [],
'1': [],
'2': [],
'3': [],
'4': [],
'5': [],
'6': [],
'7': [],
'8': []},
'RZ': {'0': [],
'1': [],
'2': [],
'3': [],
'4': [],
'5': [],
'6': [],
'7': [],
'8': []}}
Please let me know if this is sufficient, thank you!
Hi, Thank you! I can see that your code provides gate errors and timestamp. Few questions here:
@msierras
Is the timestamp the start time of each gate? and if yes, how do we retrieve the actual gate time
A characteristic is just a observation about fidelity measured at a point in time, so that timestamp is just when that fidelity was observed.
I might be misunderstanding, but if by "gate time" you're talking about the duration of each gate due to pulse duration, that's defined by the quilt calibration program - note that it's quite terse and isn't really meant to answer a generic question about "how long is this type of gate". I haven't seen any, but I'll check around for any tooling around inspecting gate timing. See the Quil-T spec for more info.
from qcs_sdk.qpu.translation import get_quilt_calibrations
print(get_quilt_calibrations("Ankaa-9Q-3"))
How do we retrieve the qubit coherence time?
The T1 and T2 times can be found from the InstructionSetArchitecture benchmarks. Note that these are also formatted as characteristic observations:
import json
from pprint import pprint
from qcs_sdk.qpu.isa import get_instruction_set_architecture
# or Ankaa-2
isa = get_instruction_set_architecture("Ankaa-9Q-3")
isa_dict = json.loads(isa.json())
benchmarks = { b["name"]: b for b in isa_dict["benchmarks"] }
T1 = {
site["node_ids"][0]: site["characteristics"]
for site in benchmarks["FreeInversionRecovery"]["sites"]
}
T2 = {
site["node_ids"][0]: site["characteristics"]
for site in benchmarks["FreeInductionDecay"]["sites"]
}
pprint({
"T1": T1,
"T2": T2
})
Will give something like
{'T1': {0: [{'error': 5.251750899754949e-06,
'name': 'T1',
'timestamp': '2024-07-24T19:02:32+00:00',
'value': 2.011880808632726e-05}],
1: [{'error': 5.4237242286098015e-06,
'name': 'T1',
'timestamp': '2024-07-24T19:03:11+00:00',
'value': 2.0207894021598053e-05}],
2: [{'error': 1.9666126145216764e-05,
'name': 'T1',
'timestamp': '2024-07-24T07:02:56+00:00',
'value': 4.2065171679768734e-05}],
3: [{'error': 1.7246100353861886e-05,
'name': 'T1',
'timestamp': '2024-07-24T19:02:56+00:00',
'value': 3.8951030114522e-05}],
4: [{'error': 4.584273351234298e-06,
'name': 'T1',
'timestamp': '2024-07-24T19:02:32+00:00',
'value': 2.04389894753998e-05}],
5: [{'error': 4.853551824266111e-06,
'name': 'T1',
'timestamp': '2024-07-24T19:02:55+00:00',
'value': 2.5018707226240363e-05}],
6: [{'error': 1.5003410468019515e-05,
'name': 'T1',
'timestamp': '2024-07-24T19:03:11+00:00',
'value': 3.5645176482455753e-05}],
7: [{'error': 1.70796939313852e-06,
'name': 'T1',
'timestamp': '2024-07-24T19:02:55+00:00',
'value': 1.4568485437102117e-05}],
8: [{'error': 1.275603218314814e-06,
'name': 'T1',
'timestamp': '2024-07-24T19:03:11+00:00',
'value': 1.4454455632761788e-05}]},
'T2': {0: [{'error': 2.2877450176163734e-06,
'name': 'T2',
'timestamp': '2024-07-24T19:02:38+00:00',
'value': 2.427571622970271e-05}],
1: [{'error': 2.522571992829871e-06,
'name': 'T2',
'timestamp': '2024-07-24T19:03:21+00:00',
'value': 3.712481213481805e-05}],
2: [{'error': 4.295848214066205e-06,
'name': 'T2',
'timestamp': '2024-07-24T19:02:40+00:00',
'value': 4.171438766634311e-05}],
3: [{'error': 1.688909417261586e-06,
'name': 'T2',
'timestamp': '2024-07-24T19:03:01+00:00',
'value': 9.266416361773806e-06}],
4: [{'error': 1.3022733837216203e-06,
'name': 'T2',
'timestamp': '2024-07-24T19:02:37+00:00',
'value': 1.1347606236184342e-05}],
5: [{'error': 1.7089140733031863e-06,
'name': 'T2',
'timestamp': '2024-07-24T13:03:47+00:00',
'value': 2.4495257490349255e-05}],
6: [{'error': 3.040908187584059e-06,
'name': 'T2',
'timestamp': '2024-07-24T19:03:17+00:00',
'value': 1.0127221667220258e-05}],
7: [{'error': 1.431987166250124e-06,
'name': 'T2',
'timestamp': '2024-07-24T19:03:04+00:00',
'value': 2.1891748908172037e-05}],
8: [{'error': 1.7203396537602246e-07,
'name': 'T2',
'timestamp': '2024-07-24T19:03:15+00:00',
'value': 1.8738250661764529e-06}]}}
If we can't retrieve them from Qiskit Rigetti, can we retrieve all these information from PyQuil v3?
All of my code snippets so far use qcs-sdk-python which can be installed independently or comes as a PyQuil v4 sub dependency. Are you still using pyQuil v3? If so, is it because you are stuck with some other conflicting dependencies? This repo should be using pyQuil v4 as of https://github.com/rigetti/qiskit-rigetti/pull/41 and we are hoping to migrate all users to pyQuil v4 as soon as possible.
@msierras looks like using something similar to https://github.com/rigetti/quil-rs/blob/66393c5dd096ce80c2585e461ea5f5e39743d817/quil-py/test/program/test_program.py#L105 you can get some analysis of time spans.
Instead of the "dummy" DEFRAME
and DEFCAL
program headers used in the test, you'd just prepend the results from the above get_quilt_calibrations
followed by your program that you want some time analysis of.
@jselig-rigetti I would like to thank you for the support and help.
First, I would like to say a huge thank you to the qiskit-rigetti team and its open community for all the valuable efforts, time, and useful resources.
We want to use the following code, which essentially reads a qiskit .qasm circuit file, transpiles it on a Rigetti quantum computer, executes it on a Rigetti quantum computer, and finally save some results data that we want in a .json file format. However the code does not run in pyQuil v4, but only runs on pyQuil v3. If there is a way to run the code below in pyQuil v4, then please let us know. Here is the code:
# Import libaries.
import json
from qiskit import execute, QuantumCircuit
from qiskit_rigetti import RigettiQCSProvider
# Load the quantum circuit from the QASM file.
qasm_file_path = f'original_circuit.qasm' # Path to the original circuit.
circuit = QuantumCircuit.from_qasm_file(qasm_file_path)
# Get simulator and backend.
p = RigettiQCSProvider()
simulator = p.get_simulator(num_qubits=4, noisy=True)
backend = p.get_backend(name='Ankaa-9Q-3')
# Transpile circuit.
transpiled_circuit = transpile(
circuits=circuit,
backend=backend,
optimization_level=3,
initial_layout=None,
)
# Save the transpiled circuit in QASM format to a file.
filename = 'transpiled_circuit.qasm'
with open(filename, 'w') as file:
file.write(transpiled_circuit.qasm())
# Execute the transpiled circuit on the simulator and backend.
simulator_job = execute(transpiled_circuit, backend=simulator, shots=1024)
backend_job = execute(transpiled_circuit, backend=backend, shots=1024)
# Grab results from the simulator and backend job.
simulator_result = simulator_job.result()
backend_result = backend_job.result()
# Convert the results to a dict.
simulator_result_dict = simulator_result.to_dict()
backend_result_dict = backend_result.to_dict()
# Create a custom dict to store it in a .json file.
result_data = {}
result_data["circuit"] = backend_result_dict["results"][0]["header"]["name"]
result_data["simulation_result"] = dict(simulator_result_dict["results"][0]["data"]["counts"]) # result_data["actual_result"] = simulator_result.get_counts()
result_data["result"] = dict(backend_result_dict["results"][0]["data"]["counts"]) # result_data["result"] = backend_result.get_counts()
result_data["depth"] = circuit.depth()
result_data["All_count"] = circuit.count_ops()
filename = 'result.json'
app_json = json.dumps(result_data)
with open(filename, 'w') as file:
json.dump(app_json, file)
Moreover, I have tried all of the ways that you have recommended previously to retrieve the gate errors and gate times of the Rigetti quantum hardware "Ankaa-9Q-3", but I could not.
The code below:
from qiskit_rigetti import RigettiQCSProvider
# Get provider and backend
p = RigettiQCSProvider()
backend = p.get_backend(name='Ankaa-9Q-3')
config = backend.configuration()
print("Backend Name:", config.backend_name)
print("Number of Qubits:", config.n_qubits)
print("Basis Gates:", config.basis_gates)
print("Coupling Map:", config.coupling_map)
print("Simulator:", config.simulator)
print("Local:", config.local)
status = backend.status()
print("Backend Operational:", status.operational)
print("Pending Jobs:", status.pending_jobs)
Gives this output:
Backend Name: Ankaa-9Q-3
Number of Qubits: 9
Basis Gates: ['u1', 'u2', 'u3', 'cx', 'id']
Coupling Map: []
Simulator: False
Local: False
and all of my transpiled circuits only consist of the basis gates u1, u2, u3, cx, and id. However, I could not find the gate errors and gate times of these basis gates in the Rigetti quantum hardware "Ankaa-9Q-3".
Thank you very much in advance. I appreciate a lot.
@jselig-rigetti I would like to also ask you what are Avg f1QRB, Avg fRO, and f1SWAP in the image below? Is there any documentation on this?
Thank you very much in advance. I appreciate a lot.
@jselig-rigetti I would like to also ask you what are Avg f1QRB, Avg fRO, and f1SWAP in the image below? Is there any documentation on this?
Thank you very much in advance. I appreciate a lot.
Hello,
Those averages are just the T1 and T2 averages for each qubit in the pair, essentially
q0-q1 Avg T1 = (q0 T1 + q1 T1) / 2
Apologies for missing your first question, I'll need a bit of time to dig into it and then I'll answer - thank you for your patience!
@jselig-rigetti In your previous answer, you are referring to Avg T1 and Avg T2 right? I am referring to Avg f1QRB, Avg fRO, and f1SWAP.
@jselig-rigetti Did you have the time to look at my first question, more specifically on the basis gates supported by Ankaa-9Q-3 and why does qiskit-rigetti always gives u1, u2, u3, cx, and id as the basis gates for all Rigetti hardware? There was a similar question at #34. @dbanty
@jselig-rigetti @dbanty Moreover, when I try to run a circuit on Ankaa-9Q-3, I get the following error. Any solution?
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
/tmp/ipykernel_244/10611352.py in <module>
----> 1 backend.run(circuit)
/opt/conda/lib/python3.9/site-packages/qiskit_rigetti/_qcs_backend.py in run(self, run_input, **options)
151
152 if self._qc is None:
--> 153 self._qc = get_qc(
154 self.configuration().backend_name,
155 compiler_timeout=self._compiler_timeout,
/opt/conda/lib/python3.9/site-packages/pyquil/api/_quantum_computer.py in get_qc(***failed resolving arguments***)
848
849 # 4. Not a special case, query the web for information about this quantum_processor.
--> 850 quantum_processor = get_qcs_quantum_processor(
851 quantum_processor_id=prefix, client_configuration=client_configuration
852 )
/opt/conda/lib/python3.9/site-packages/pyquil/quantum_processor/qcs.py in get_qcs_quantum_processor(quantum_processor_id, client_configuration, timeout)
77 client_configuration = client_configuration or QCSClientConfiguration.load()
78 with qcs_client(client_configuration=client_configuration, request_timeout=timeout) as client: # type: httpx.Client
---> 79 isa = get_instruction_set_architecture(client=client, quantum_processor_id=quantum_processor_id).parsed
80
81 return QCSQuantumProcessor(quantum_processor_id=quantum_processor_id, isa=isa)
/opt/conda/lib/python3.9/site-packages/qcs_api_client/types.py in parsed(self)
65 """
66 if self._parsed is None:
---> 67 self._parsed = self._parse_function(response=self)
68
69 return self._parsed
/opt/conda/lib/python3.9/site-packages/qcs_api_client/api/quantum_processors/get_instruction_set_architecture.py in _parse_response(response)
21 raise_for_status(response)
22 if response.status_code == 200:
---> 23 response_200 = InstructionSetArchitecture.from_dict(response.json())
24
25 return response_200
/opt/conda/lib/python3.9/site-packages/qcs_api_client/models/instruction_set_architecture.py in from_dict(src_dict)
61 def from_dict(src_dict: Dict[str, Any]) -> "InstructionSetArchitecture":
62 d = src_dict.copy()
---> 63 architecture = Architecture.from_dict(d.pop("architecture"))
64
65 benchmarks = []
/opt/conda/lib/python3.9/site-packages/qcs_api_client/models/architecture.py in from_dict(src_dict)
75 edges.append(edges_item)
76
---> 77 family = Family(d.pop("family"))
78
79 nodes = []
/opt/conda/lib/python3.9/enum.py in __call__(cls, value, names, module, qualname, type, start)
382 """
383 if names is None: # simple value lookup
--> 384 return cls.__new__(cls, value)
385 # otherwise, functional API: we're creating a new Enum type
386 return cls._create_(
/opt/conda/lib/python3.9/enum.py in __new__(cls, value)
700 ve_exc = ValueError("%r is not a valid %s" % (value, cls.__qualname__))
701 if result is None and exc is None:
--> 702 raise ve_exc
703 elif exc is None:
704 exc = TypeError(
ValueError: 'Ankaa' is not a valid Family
@GeorgiosIoannouCoder Sorry for missing your questions earlier - I'm not sure I can answer your questions completely, but:
In your previous answer, you are referring to Avg T1 and Avg T2 right? I am referring to Avg f1QRB, Avg fRO, and f1SWAP.
It's similar for all the Avg ...
data in the 2Q columns, they're just the sum of those fidelities for the constituent nodes divided by 2. (e.g. 2Q 0-1
is the sum of 1Q 0
and 1
)
Did you have the time to look at my first question, more specifically on the basis gates supported by Ankaa-9Q-3 and why does qiskit-rigetti always gives u1, u2, u3, cx, and id as the basis gates for all Rigetti hardware?
It looks to just be hardcoded that way, see https://github.com/rigetti/qiskit-rigetti/blob/main/qiskit_rigetti/_qcs_provider.py#L122. Those gates are supported for execution on our QPUs. Native gate support can be found on https://qcs.rigetti.com/qpus, but QuilC will decompose other gates e.g. CZ
into the equivalent RZ
, RX
, and ISWAP
instructions, so input programs can still have CZ
.
However, I could not find the gate errors and gate times of these basis gates in the Rigetti quantum hardware "Ankaa-9Q-3".
Unfortunately these aren't available from the qiskit-rigetti
package (yet? there are some efforts like https://github.com/rigetti/qiskit-rigetti/issues/24) but are available directly from our API and SDK. Currently the gate errors can be found from the InstructionSetArchitecture as outlined in https://github.com/rigetti/qiskit-rigetti/issues/54#issuecomment-2248773751 and the gate duration can be found by using https://github.com/rigetti/qiskit-rigetti/issues/54#issuecomment-2251008328.
ValueError: 'Ankaa' is not a valid Family
This error is from using PyQuil v3, which is no longer supported. You should upgrade to PyQuil v4, preferably the latest 4.13.1
. Which version of qiskit-rigetti
are you using? The latest is 0.4.7 which requires PyQuil 4.0+.
https://github.com/rigetti/qiskit-rigetti/issues/54#issuecomment-2252194796 However the code does not run in pyQuil v4, but only runs on pyQuil v3. If there is a way to run the code below in pyQuil v4, then please let us know.
It looks like you are using transpile
here, which I think is from qiskit 1.0+. Currently this package requires qiskit = ">=0.38.0,<1.0.0
although there are efforts to update this e.g. https://github.com/rigetti/qiskit-rigetti/pull/50. Without a copy of your original original_circuit.qasm
I'm not sure if the problem is in there, but the example at https://github.com/rigetti/qiskit-rigetti?tab=readme-ov-file#usage should work with PyQuil v4. Note that QuilC and our QPUs only support OPENQASM 2.0
.
@jselig-rigetti I would like to thank you for your answers. When I try to run the example at https://github.com/rigetti/qiskit-rigetti?tab=readme-ov-file#usage via the JupyterLab PyQuil v4 provided by Rigetti I get the following error:
/opt/conda/lib/python3.9/site-packages/qiskit/circuit/equivalence.py:18: DeprecationWarning: The retworkx package is deprecated and has been renamed to rustworkx. Rustworkx is a drop-in replacement and can be used by replacing `import retworkx` with import `rustworkx`.
import retworkx as rx
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
/tmp/ipykernel_709/1860552683.py in <module>
1 from qiskit import execute
----> 2 from qiskit_rigetti import RigettiQCSProvider, QuilCircuit
3
4 # Get provider and backend
5 p = RigettiQCSProvider()
/opt/conda/lib/python3.9/site-packages/qiskit_rigetti/__init__.py in <module>
17
18 from ._quil_circuit import QuilCircuit
---> 19 from ._qcs_backend import RigettiQCSBackend
20 from ._qcs_job import RigettiQCSJob
21 from ._qcs_provider import RigettiQCSProvider
/opt/conda/lib/python3.9/site-packages/qiskit_rigetti/_qcs_backend.py in <module>
18
19 from pyquil import get_qc
---> 20 from pyquil.api import QuantumComputer, EngagementManager
21 from qcs_api_client.client import QCSClientConfiguration
22 from qiskit import QuantumCircuit, ClassicalRegister
ImportError: cannot import name 'EngagementManager' from 'pyquil.api' (/opt/conda/lib/python3.9/site-packages/pyquil/api/__init__.py)
Why is this error occurring? Here are the libraries and their versions provided by Rigetti by default:
Package Version
----------------------------- ---------------
alembic 1.7.5
altair 4.1.0
anyio 3.3.4
appdirs 1.4.4
argon2-cffi 21.1.0
astunparse 1.6.3
async-generator 1.10
attrs 20.3.0
Babel 2.9.1
backcall 0.2.0
backports.functools-lru-cache 1.6.4
beautifulsoup4 4.12.3
bleach 4.1.0
blinker 1.4
bokeh 2.4.1
Bottleneck 1.3.2
brotlipy 0.7.0
cached-property 1.5.2
cachetools 4.2.4
certifi 2021.5.30
certipy 0.1.3
cffi 1.15.0
chardet 4.0.0
charset-normalizer 2.0.0
cirq 0.12.0
cirq-aqt 0.12.0
cirq-core 0.12.0
cirq-google 0.12.0
cirq-ionq 0.12.0
cirq-pasqal 0.12.0
cirq-rigetti 0.12.0
cirq-web 0.12.0
click 8.0.3
cloudpickle 2.0.0
colorama 0.4.4
conda 4.10.3
conda-package-handling 1.7.3
cryptography 35.0.0
cycler 0.11.0
Cython 0.29.24
cytoolz 0.11.2
dask 2021.11.1
debugpy 1.5.1
decorator 5.1.0
defusedxml 0.7.1
Deprecated 1.2.14
dill 0.3.4
distlib 0.3.8
distributed 2021.11.1
dlx 1.0.4
docplex 2.20.204
entrypoints 0.3
execnb 0.1.5
fastcore 1.5.29
fastdtw 0.3.4
fastjsonschema 2.19.1
filelock 3.13.1
frozendict 2.4.0
fsspec 2021.11.0
ghapi 1.0.4
gitdb 4.0.11
GitPython 3.1.42
gmpy2 2.1.0rc1
google-api-core 1.32.0
google-auth 1.35.0
googleapis-common-protos 1.56.0
greenlet 1.1.2
grpcio 1.62.0
h11 0.9.0
h5py 3.4.0
HeapDict 1.0.1
html5lib 1.1
httpcore 0.11.1
httpx 0.15.5
idna 2.10
imagecodecs 2021.8.26
imageio 2.9.0
importlib-metadata 4.8.2
importlib-resources 5.4.0
inflection 0.5.1
ipykernel 6.5.0
ipympl 0.8.2
ipython 7.29.0
ipython-genutils 0.2.0
ipywidgets 7.6.5
iso8601 0.1.16
jedi 0.18.0
Jinja2 3.0.3
joblib 1.1.0
json5 0.9.5
jsonschema 4.2.1
jupyter-client 7.0.6
jupyter-core 4.9.1
jupyter-server 1.11.2
jupyter-server-mathjax 0.2.6
jupyter-telemetry 0.1.0
jupyterhub 1.5.0
jupyterlab 3.2.3
jupyterlab-git 0.38.0
jupyterlab-pygments 0.1.2
jupyterlab-server 2.8.2
jupyterlab-widgets 1.0.2
kiwisolver 1.3.2
lark 0.11.3
llvmlite 0.37.0
locket 0.2.0
lxml 5.1.0
Mako 1.1.5
mamba 0.17.0
MarkupSafe 2.0.1
matplotlib 3.4.3
matplotlib-inline 0.1.6
mistune 0.8.4
mock 4.0.3
more-itertools 10.2.0
mpmath 1.2.1
msgpack 1.0.2
multitasking 0.0.11
nb_conda_kernels 2.3.1
nbclassic 0.3.4
nbclient 0.5.8
nbconvert 6.3.0
nbdev 2.1.1
nbdime 3.2.1
nbformat 5.1.3
nest-asyncio 1.5.1
networkx 2.6.3
notebook 6.4.5
numba 0.54.1
numexpr 2.7.3
numpy 1.26.4
oauthlib 3.1.1
olefile 0.46
packaging 23.2
pamela 1.0.0
pandas 1.3.4
pandocfilters 1.5.0
parso 0.8.2
partd 1.2.0
patsy 0.5.2
peewee 3.17.1
pexpect 4.8.0
pickleshare 0.7.5
Pillow 8.4.0
pip 21.3.1
platformdirs 2.6.2
plotly 5.9.0
ply 3.11
pooch 1.5.2
prometheus-client 0.12.0
prompt-toolkit 3.0.22
protobuf 3.13.0
psutil 5.8.0
ptyprocess 0.7.0
py 1.11.0
pyasn1 0.5.1
pyasn1-modules 0.3.0
pybind11 2.11.1
pycosat 0.6.3
pycparser 2.21
pycurl 7.44.1
pydantic 1.8.2
Pygments 2.10.0
PyJWT 1.7.1
pyOpenSSL 21.0.0
pyparsing 2.4.7
pyquil 4.7.0
pyrsistent 0.18.0
PySocks 1.7.1
pyspnego 0.10.2
python-constraint 1.4.0
python-dateutil 2.8.2
python-json-logger 2.0.1
python-rapidjson 1.16
pytz 2024.1
pytz-deprecation-shim 0.1.0.post0
PyWavelets 1.2.0
PyYAML 6.0
pyzmq 22.3.0
qcs-api-client 0.8.0
qcs-sdk-python 0.17.0
qiskit 0.27.0
qiskit-aer 0.8.2
qiskit-aqua 0.9.2
qiskit-ibmq-provider 0.14.0
qiskit-ignis 0.6.0
qiskit-rigetti 0.4.5
qiskit-terra 0.17.4
Quandl 3.7.0
quil 0.6.6
requests 2.31.0
requests-ntlm 1.2.0
retry 0.9.2
retrying 1.3.4
retworkx 0.14.1
rfc3339 6.2
rfc3986 1.5.0
rpcq 3.11.0
rpy2 3.4.5
rsa 4.9
ruamel.yaml 0.17.17
ruamel.yaml.clib 0.2.6
ruamel-yaml-conda 0.15.80
rustworkx 0.14.1
scikit-image 0.18.3
scikit-learn 1.0.1
scipy 1.12.0
seaborn 0.11.2
Send2Trash 1.8.0
setuptools 59.1.1
simplegeneric 0.8.1
six 1.16.0
smmap 5.0.1
sniffio 1.2.0
sortedcontainers 2.4.0
soupsieve 2.3
SQLAlchemy 1.4.27
statsmodels 0.13.1
sympy 1.9
tables 3.6.1
tblib 1.7.0
tenacity 8.2.3
terminado 0.12.1
testpath 0.5.0
threadpoolctl 3.0.0
tifffile 2021.11.2
toml 0.10.2
toolz 0.11.2
tornado 6.1
tqdm 4.62.3
traitlets 5.1.1
types-Deprecated 1.2.9.20240106
types-python-dateutil 2.8.19.20240106
types-retry 0.9.9.4
typing_extensions 4.10.0
tzdata 2021.5
tzlocal 4.1
urllib3 1.26.7
virtualenv 20.16.3
wcwidth 0.2.5
webencodings 0.5.1
websocket-client 1.2.1
wheel 0.37.0
widgetsnbextension 3.5.2
wrapt 1.16.0
xlrd 2.0.1
yfinance 0.2.37
zict 2.0.0
zipp 3.6.0
@GeorgiosIoannouCoder apologies, we're in the process of upgrading the base image for our JupyterLab notebooks which should fix this error.
In the mean time, you can fix the dependencies in your instance by doing the following:
conda install qiskit==0.46.2 && pip install qiskit==0.46.2 qiskit-rigetti==0.4.7
.ipynb
Python3 Notebook and run Kernel -> Restart Kernel... and click Restart to confirm.After that the correct versions of the dependencies should be installed and available, so the code should run.
~Please note, if you are trying to execute on the live Ankaa-9Q-3
processor, it is currently under maintenance - we will provide updates at https://rigetti.statuspage.io/ when that changes. Ankaa-2
is still available.~ Ankaa-9Q-3
is available again.
Hello, I'm having trouble running the noiseless simulator (9q-square-qvm) at the same time as the hardware (Ankaa-9Q-3).
To troubleshoot the issue I am using the "9q-square-noisy-qvm" noisy simulator in place of "Ankaa-9Q-3"
When I try to run the execution script it keeps timing out on the randomly generated random_circuit_n.qasm files that have 9 qubits.
It's specifically timing out on the noiseless simulator's task of getting actual_result. The nosiy simulator has the task of getting all_count and the depth and that seems to be running fine.
Here is my code that I'm running using rigetti's jupyter notebook with pyquil v4.
Packages:
!pip install --upgrade pyquil
!pip install opentelemetry-api opentelemetry-sdk
Random circuit generator script using Ankaa-9Q-3 native gates: (Create 'random_circuits_purely_p4' directory)
import random
import os
from pyquil import Program
from pyquil.gates import RZ, RX, CZ, ISWAP
# Parameters
num_circuits = 5
min_depth = 5
max_depth = 50
min_qubits = 5
max_qubits = 9
random_circuits_directory = 'random_circuits_purely_p4'
def generate_random_circuits(num_circuits, min_depth, max_depth, min_qubits, max_qubits, output_directory):
# Ensure the output directory exists
os.makedirs(output_directory, exist_ok=True)
for i in range(num_circuits):
# Randomly select the number of qubits and depth for this circuit
num_qubits = random.randint(min_qubits, max_qubits)
depth = random.randint(min_depth, max_depth)
# Initialize a new program for this circuit
circuit = Program()
# Add random gates to the circuit
for _ in range(depth):
# Randomly select a gate and qubits to apply it to
gate_choice = random.choice(['RZ', 'RX', 'CZ', 'ISWAP'])
if gate_choice in ['RZ', 'RX']:
# Single-qubit gate
qubit = random.randint(0, num_qubits - 1)
angle = random.uniform(0, 2 * 3.141592653589793) # Random angle between 0 and 2π
if gate_choice == 'RZ':
gate = RZ(angle, qubit)
else:
gate = RX(angle, qubit)
else:
# Two-qubit gate
qubit1, qubit2 = random.sample(range(num_qubits), 2)
if gate_choice == 'CZ':
gate = CZ(qubit1, qubit2)
else:
gate = ISWAP(qubit1, qubit2)
# Add the gate to the circuit
circuit.inst(gate)
# Add a comment with the number of qubits
qasm_output = circuit.out()
qasm_output = f"// QUBITS: {num_qubits}\n" + qasm_output
# Save the original circuit as a QASM file
file_path = os.path.join(output_directory, f"random_circuit_{i+1}.qasm")
with open(file_path, 'w') as file:
file.write(qasm_output)
print(f"Random circuit {i + 1} exported to {file_path}")
# Call the function with the specified parameters
generate_random_circuits(num_circuits, min_depth, max_depth, min_qubits, max_qubits, random_circuits_directory)
Execution script:
import os
import json
import time
import uuid
from collections import Counter
from datetime import datetime
from pyquil import Program
from pyquil.api import get_qc
from pyquil.gates import MEASURE
from pyquil.quilbase import Gate
from concurrent.futures import ThreadPoolExecutor
# Parameters
random_circuits_directory = 'random_circuits_purely_p4'
executed_circuits_directory = 'executed_circuits_purely_p4'
total_shots = 8192
delay_between_executions = 40 # Seconds between each circuit execution
max_retries = 3 # Maximum number of retries for execution
# Initialize the simulators
noiseless_qc_name = "9q-square-qvm" # Noiseless simulator
noisy_qc_name = "9q-square-noisy-qvm" # Noisy simulator
noiseless_qc = get_qc(noiseless_qc_name, as_qvm=True)
noisy_qc = get_qc(noisy_qc_name, as_qvm=True)
def get_num_qubits_from_qasm(qasm_data):
"""Look for the QUBITS comment to determine the number of qubits."""
for line in qasm_data.splitlines():
if line.startswith('// QUBITS:'):
return int(line.split(':')[1].strip())
return 1 # Default to 1 qubit if not found
def calculate_depth(program):
"""Calculate the depth of a Quil program."""
qubit_layers = {}
for inst in program:
if isinstance(inst, Gate):
qubits = [q.index for q in inst.qubits]
max_layer = max(qubit_layers.get(qubit, 0) for qubit in qubits)
for qubit in qubits:
qubit_layers[qubit] = max_layer + 1
# Depth is the maximum number of layers any qubit reached
depth = max(qubit_layers.values(), default=0)
return depth
def count_gates(program):
"""Count the occurrences of each gate in a Quil program."""
gate_counter = Counter()
for inst in program:
if isinstance(inst, Gate):
gate_counter[inst.name] += 1
return dict(gate_counter)
def run_noiseless_simulation(circuit, circuit_name):
"""Run noiseless simulation and return the result."""
actual_result = {}
for attempt in range(1, max_retries + 1):
try:
print(f"Running noiseless simulation for {circuit_name}, attempt {attempt}...")
exe_noiseless = noiseless_qc.compile(circuit.wrap_in_numshots_loop(total_shots))
result_noiseless = noiseless_qc.run(exe_noiseless)
measurements_noiseless = result_noiseless.get_register_map()
for measurement in measurements_noiseless['ro']:
key = ''.join(map(str, measurement))
if key not in actual_result:
actual_result[key] = 0
actual_result[key] += 1
print(f"Noiseless simulation completed for {circuit_name}.")
break
except Exception as e:
print(f"Error executing on noiseless_qc (attempt {attempt}): {str(e)}")
if attempt == max_retries:
print(f"Max retries reached for noiseless simulation of {circuit_name}.")
else:
time.sleep(delay_between_executions) # Delay before retrying
return actual_result
def compile_and_simulate_circuit(filename):
# Generate a unique job ID
job_id = str(uuid.uuid4())
# Read the QASM file
input_path = os.path.join(random_circuits_directory, filename)
with open(input_path, 'r') as file:
qasm_data = file.read()
# Determine the number of qubits from the QASM file
num_qubits = get_num_qubits_from_qasm(qasm_data)
# Filter out comments and empty lines for actual PyQuil instructions
pyquil_instructions = "\n".join(line for line in qasm_data.splitlines() if not line.startswith('//') and line.strip())
# Create a program from the PyQuil instructions
circuit = Program(pyquil_instructions)
# Declare memory for measurement results based on the number of qubits
ro = circuit.declare('ro', 'BIT', num_qubits)
for qubit in range(num_qubits):
circuit += MEASURE(qubit, ro[qubit])
# Create a subdirectory for each circuit
circuit_name = filename.replace(".qasm", "")
circuit_subdirectory = os.path.join(executed_circuits_directory, circuit_name)
os.makedirs(circuit_subdirectory, exist_ok=True)
# Save the original circuit in the subdirectory
original_file_path = os.path.join(circuit_subdirectory, filename)
with open(original_file_path, 'w') as file:
file.write(qasm_data)
# Run the noiseless simulation to get the actual result
actual_result = run_noiseless_simulation(circuit, circuit_name)
# Compile the circuit to get the depth and gate counts using the noisy simulator
try:
compiled_program = noisy_qc.compiler.quil_to_native_quil(circuit)
depth = calculate_depth(compiled_program)
all_count = count_gates(compiled_program)
except Exception as e:
print(f"Error compiling on noisy_qc: {str(e)}")
return
# Save the compiled circuit as a QASM file in the same subdirectory
compiled_qasm_output = compiled_program.out() # Get QASM output
compiled_filename = filename.replace("random", "compiled")
compiled_file_path = os.path.join(circuit_subdirectory, compiled_filename)
with open(compiled_file_path, 'w') as file:
file.write(compiled_qasm_output)
# Initialize a dictionary to accumulate results with ordered entries
result_data = {
"circuit": circuit_name,
"actual_result": actual_result, # From noiseless simulator
"backend_name": noisy_qc_name, # From noisy simulator
"backend-version": "ADD THIS",
"job_id": job_id,
"date": datetime.now().isoformat(),
"shots": total_shots,
"depth": depth, # From noisy simulator
"all_count": all_count # From noisy simulator
}
# Save the results as a JSON file in the same subdirectory
result_filename = filename.replace("original", "result").replace(".qasm", ".json")
result_file_path = os.path.join(circuit_subdirectory, result_filename)
with open(result_file_path, 'w') as file:
json.dump(result_data, file, indent=4)
print(f"Random, compiled, and result files exported to {circuit_subdirectory}")
def compile_and_save_circuits(input_directory, output_directory):
# Ensure the executed circuits directory exists
os.makedirs(output_directory, exist_ok=True)
qasm_files = [f for f in os.listdir(input_directory) if f.endswith(".qasm")]
for filename in qasm_files:
compile_and_simulate_circuit(filename)
# Add a delay between each circuit execution
time.sleep(delay_between_executions)
# Call the function with the specified directories
compile_and_save_circuits(random_circuits_directory, executed_circuits_directory)
Console output after running above code:
Running noiseless simulation for random_circuit_3, attempt 1...
Noiseless simulation completed for random_circuit_3.
Random, compiled, and result files exported to executed_circuits_purely_p4/random_circuit_3
Running noiseless simulation for random_circuit_4, attempt 1...
Error executing on noiseless_qc (attempt 1): Could not communicate with QVM at http://127.0.0.1:5000
Running noiseless simulation for random_circuit_4, attempt 2...
Error executing on noiseless_qc (attempt 2): Could not communicate with QVM at http://127.0.0.1:5000
Running noiseless simulation for random_circuit_4, attempt 3...
Error executing on noiseless_qc (attempt 3): Could not communicate with QVM at http://127.0.0.1:5000
Max retries reached for noiseless simulation of random_circuit_4.
Random, compiled, and result files exported to executed_circuits_purely_p4/random_circuit_4
Running noiseless simulation for random_circuit_1, attempt 1...
Noiseless simulation completed for random_circuit_1.
Random, compiled, and result files exported to executed_circuits_purely_p4/random_circuit_1
Running noiseless simulation for random_circuit_2, attempt 1...
Error executing on noiseless_qc (attempt 1): Could not communicate with QVM at http://127.0.0.1:5000
Running noiseless simulation for random_circuit_2, attempt 2...
Error executing on noiseless_qc (attempt 2): Could not communicate with QVM at http://127.0.0.1:5000
Please let me know what I can do to fix the error "Could not communicate with QVM at http://127.0.0.1:500"
@msierras
Please let me know what I can do to fix the error "Could not communicate with QVM at http://127.0.0.1:5000"
Hello,
I think this may be a problem with your JupyterHub instance, I was able to run your code successfully.
You could try one of two things:
qvm -S &
to launch the QVM in server mode as a background task.You should be able to verify that the QVM is running on your instance by running the following in your notebook's terminal:
curl -X POST -d '{"type": "ping"}' http://127.0.0.1:5000
# should return `pong <some number>`
If the problem persists, please reach out to support@rigetti.com as that type of error isn't related to the qiskit-rigetti
project.
@jselig-rigetti Thank you very much for everything. My last question is: How to get information from attached images through pyquil v4 code and not having to manually download via the excel .csv on the Rigetti website. Moreover, how to get the gate time for each supported native gate via pyquil v4 code?
@jselig-rigetti Sorry for asking one more question, but how would we get the qubit measurement error?
我在网上找的关于grover算法的代码,有from qiskit import QuantumCircuit, execute这句代码,但是我下载qiskit1.1.1版本的软件包,运行时出现了错误,ImportError: cannot import name 'execute' from 'qiskit'。我在网上看到的解决办法是需要下载低版本的软件包。但是我在下载qiskit0.40版本的软件包时,遇到了问题,不知道怎么解决。
@msierras
Hello,
How do I get gate error rate?
Please check if something like https://github.com/rigetti/qiskit-rigetti/issues/54#issuecomment-2248131283 would work for your purposes. If not, please let me know if there is something specific missing. Note that only native gate fidelities are listed - user programs can be translated into native programs using QuilC.
How do I get the gate time for each supported gate?
This one is a little trickier - we'll work to make something like this into more of a utility, but you can do something like the following:
from typing import Union
from quil.program import Program as QuilProgram
from quil.instructions import Gate
from qcs_sdk.qpu.translation import get_quilt_calibrations
from pyquil import get_qc, Program
def get_gate_durations_nanoseconds(
qpu_name: str,
user_program: Union[Program, None] = None
) -> dict[Gate, int]:
"""
If `user_program` is provided, the gate times returned
will only be for gates that are present in the program.
Note that the program is first translated into native quil.
If `user_program` is None, all times for all supported
gates will be returned. Note that the same gate may have
different times for different qubits.
"""
# The Quil-T header contains all information about gate execution times.
quilt_calibrations = get_quilt_calibrations(qpu_name)
quilt_program = QuilProgram.parse(quilt_calibrations)
gates: list[Gate] = []
if user_program is None:
gates = [
Gate(cal.name, cal.parameters, cal.qubits, cal.modifiers)
for cal in quilt_program.calibrations.calibrations
]
else:
native_program = QuilProgram.parse(
get_qc(qpu_name).compiler.quil_to_native_quil(user_program).out()
)
gates = [
gate for gate in [
instruction.as_gate()
for instruction in native_program.body_instructions
]
if gate is not None
]
by_gate_nanoseconds = {}
for gate in gates:
calibration = quilt_program.calibrations.get_match_for_gate(gate)
calibration_program = QuilProgram()
calibration_program.add_instructions(calibration.instructions)
# anticipating that each gate only has a single block
block = calibration_program.control_flow_graph().basic_blocks()[0]
schedule = block.as_schedule_seconds(quilt_program)
by_gate_nanoseconds[gate] = int(schedule.duration() / 1e-9)
return by_gate_nanoseconds
# An example user program
user_program = Program("""
DECLARE ro BIT[1]
H 0
RX(pi) 1
CNOT 0 1
MEASURE 1 ro[0]
""")
print()
print("Gate times for user program:")
for gate, time in get_gate_durations_nanoseconds("Ankaa-9Q-3", user_program).items():
print(f"{gate.to_quil()}: {time} ns")
print()
print("Gate times for all supported gates:")
for gate, time in get_gate_durations_nanoseconds("Ankaa-9Q-3").items():
print(f"{gate.to_quil()}: {time} ns")
Note that if you are coming from QASM, you can translate to quil using:
user_program = get_qc("Ankaa-9Q-3").compiler.transpile_qasm_2("...")
@freetoone-seo
Hmm, you may need to delete your venv
directory and then reinstall project dependencies.
What is the output from pip freeze
?
@jselig-rigetti
Thank you for the reply!
For the second code snippet you sent regarding gate times I am unable to run the code due to an error. I am using the latest version of pyquil 4 in rigetti's online Jupyter Notebook for reference, maybe my Juptyer Notebook environment is causing the error.
Here is the error I receive:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/tmp/ipykernel_195/2932446761.py in <module>
72 print()
73 print("Gate times for user program:")
---> 74 for gate, time in get_gate_durations_nanoseconds("Ankaa-9Q-3", user_program).items():
75 print(f"{gate.to_quil()}: {time} ns")
76
/tmp/ipykernel_195/2932446761.py in get_gate_durations_nanoseconds(qpu_name, user_program)
50
51 # anticipating that each gate only has a single block
---> 52 block = calibration_program.control_flow_graph().basic_blocks()[0]
53 schedule = block.as_schedule_seconds(quilt_program)
54
AttributeError: 'quil.program.Program' object has no attribute 'control_flow_graph'
@jselig-rigetti
When running the code shown below, MEASURE has a value. Is the value in MEASURE the success probability of measurement operation? Is the measurement error "1 - value"?
import json
from pprint import pprint
from qcs_sdk.qpu.isa import get_instruction_set_architecture
# or Ankaa-2
isa = get_instruction_set_architecture("Ankaa-9Q-3")
# Since the `isa` object is implemented in Rust and only exposed with Python bindings,
# it can be tricky to use directly. I recommend starting with the regular `isa` object
# because it provides type annotations, but it can also be converted to a dictionary.
isa_dict = json.loads(isa.json())
# The InstructionSetArchitecture format is not dictionary-like,
# but it can be converted to one without much trouble.
instructions = {
instr["name"]: {
"-".join([str(node_id) for node_id in site["node_ids"]]): site["characteristics"]
for site in instr["sites"]
}
for instr in isa_dict["instructions"]
}
pprint(instructions)
Output with value highlighted:
@msierras
For the second code snippet you sent regarding gate times I am unable to run the code due to an error.
Apologies, if you are running this in the jupyterhub notebook please do the following:
!pip install --upgrade --force-reinstall qiskit-rigetti==0.4.7 pyquil==4.11 qiskit==0.46.1 shortuuid
Which should look like:
pip install
.That should allow the example with get_gate_durations_nanoseconds
to run.
Is the value in MEASURE the success probability of measurement operation? Is the measurement error "1 - value"?
That's the case, yes.
To get the properties of a backend in Qiskit, you typically use the properties() and then do properties().to_dict() to get the qubit and gate errors in a dictionary format. Is it possible to do this when using qiskit-rigetti? If not, what is the best alternative?