diff --git a/checks-superstaq/checks_superstaq/all_.py b/checks-superstaq/checks_superstaq/all_.py index 39844e91f..0a3342351 100644 --- a/checks-superstaq/checks_superstaq/all_.py +++ b/checks-superstaq/checks_superstaq/all_.py @@ -19,12 +19,11 @@ ) -def run(*args: str, sphinx_paths: list[str] | None = None) -> int: +def run(*args: str) -> int: """Runs all checks on the repository. Args: *args: Command line arguments. - sphinx_paths: List of sphinx paths strings (used for building docs). Returns: Terminal exit code. 0 indicates success, while any other integer indicates a test failure. @@ -96,7 +95,8 @@ def run(*args: str, sphinx_paths: list[str] | None = None) -> int: if default_mode: # checks that the docs build checks_failed |= build_docs.run( - *args_to_pass, exit_on_failure=exit_on_failure, sphinx_paths=sphinx_paths + *args_to_pass, + exit_on_failure=exit_on_failure, ) return checks_failed diff --git a/checks-superstaq/checks_superstaq/build_docs.py b/checks-superstaq/checks_superstaq/build_docs.py index 7ebced64b..f57a1ab52 100755 --- a/checks-superstaq/checks_superstaq/build_docs.py +++ b/checks-superstaq/checks_superstaq/build_docs.py @@ -10,12 +10,11 @@ @check_utils.enable_exit_on_failure -def run(*args: str, sphinx_paths: list[str] | None = None) -> int: +def run(*args: str) -> int: """Checks that the docs build successfully. Args: *args: Command line arguments. - sphinx_paths: List of sphinx paths (passed to `sphinx-apidoc`). Returns: Terminal exit code. 0 indicates success, while any other integer indicates a test failure. @@ -32,17 +31,12 @@ def run(*args: str, sphinx_paths: list[str] | None = None) -> int: return 0 docs_dir = os.path.join(check_utils.root_dir, "docs") - - if sphinx_paths: - returncode = 0 - for path in sphinx_paths: - returncode |= subprocess.call( - ["sphinx-apidoc", "-f", "-o", "source", path, f"{path}/*_test.py"], cwd=docs_dir - ) - return subprocess.call(["sphinx-build", "source", "build/html"], cwd=docs_dir) - else: + if not os.path.isdir(os.path.join(docs_dir, "source")): print(check_utils.warning("No docs to build.")) return 0 + return subprocess.call( + ["sphinx-build", "source", "build/html", "--fail-on-warning", "--keep-going"], cwd=docs_dir + ) if __name__ == "__main__": diff --git a/checks-superstaq/requirements.txt b/checks-superstaq/requirements.txt index c7ab6d070..c68f43b18 100644 --- a/checks-superstaq/requirements.txt +++ b/checks-superstaq/requirements.txt @@ -19,4 +19,5 @@ pytest-socket>=0.7.0 pytest-xdist>=3.4.0 ruff>=0.5.6 setuptools>=67.0.0 +sphinx-autoapi>=3.2.1 sphinx-rtd-theme>=1.0.0 diff --git a/checks/build_docs.py b/checks/build_docs.py index 8124fa4f3..0f18e8b4d 100755 --- a/checks/build_docs.py +++ b/checks/build_docs.py @@ -9,11 +9,5 @@ exit( checks.build_docs.run( *sys.argv[1:], - sphinx_paths=[ - "../cirq-superstaq", - "../qiskit-superstaq", - "../general-superstaq", - "../supermarq-benchmarks", - ], ) ) diff --git a/cirq-superstaq/cirq_superstaq/job.py b/cirq-superstaq/cirq_superstaq/job.py index 52e5d9569..539dd411d 100644 --- a/cirq-superstaq/cirq_superstaq/job.py +++ b/cirq-superstaq/cirq_superstaq/job.py @@ -157,13 +157,14 @@ def status(self, index: int | None = None) -> str: current status. A full list of states is given in `cirq_superstaq.Job.ALL_STATES`. Args: - index: The index of the specific job status. + index: An optional index of the specific sub-job to cancel. + + Raises: + ~gss.SuperstaqServerException: If unable to get the status of the job + from the API. Returns: The status of the job indexed by `index` or the overall job status if `index` is `None`. - - Raises: - gss.SuperstaqServerException: If unable to retrieve the status of the job from the API. """ if index is None: self._refresh_job() @@ -189,8 +190,8 @@ def cancel(self, index: int | None = None, **kwargs: object) -> None: kwargs: Extra options needed to fetch jobs. Raises: - gss.SuperstaqServerException: If unable to get the status of the job from the API or - cancellations were unsuccessful. + ~gss.SuperstaqServerException: If unable to get the status of the job + from the API or cancellations were unsuccessful. """ job_ids = self._job_id.split(",") ids_to_cancel = [job_ids[index]] if index else job_ids @@ -203,9 +204,10 @@ def target(self) -> str: The target to which this job was submitted. Raises: - gss.SuperstaqUnsuccessfulJobException: If the job failed or has been canceled or - deleted. - gss.SuperstaqServerException: If unable to get the status of the job from the API. + ~gss.SuperstaqUnsuccessfulJobException: If the job failed or has been + canceled or deleted. + ~gss.SuperstaqServerException: If unable to get the status of the job + from the API. """ first_job_id = self._job_id.split(",")[0] if (first_job_id not in self._job) or "target" not in self._job[first_job_id]: @@ -229,9 +231,10 @@ def num_qubits(self, index: int | None = None) -> int | list[int]: number for the given circuit index. Raises: - gss.SuperstaqUnsuccessfulJobException: If the job failed or has been canceled or - deleted. - gss.SuperstaqServerException: If unable to get the status of the job from the API. + ~gss.SuperstaqUnsuccessfulJobException: If the job failed or has been + canceled or deleted. + ~gss.SuperstaqServerException: If unable to get the status of the job + from the API. """ job_ids = self._job_id.split(",") if not all( @@ -253,9 +256,10 @@ def repetitions(self) -> int: The number of repetitions for this job. Raises: - gss.SuperstaqUnsuccessfulJobException: If the job failed or has been canceled or - deleted. - gss.SuperstaqServerException: If unable to get the status of the job from the API. + ~gss.SuperstaqUnsuccessfulJobException: If the job failed or has been + canceled or deleted. + ~gss.SuperstaqServerException: If unable to get the status of the job + from the API. """ first_job_id = self._job_id.split(",")[0] if (first_job_id not in self._job) or "shots" not in self._job[first_job_id]: @@ -415,9 +419,9 @@ def counts( `index` or a list of such dictionaries for each respective sub-job. Raises: - gss.SuperstaqUnsuccessfulJobException: If the job failed or has been canceled or - deleted. - gss.SuperstaqServerException: If unable to get the results from the API. + ~gss.SuperstaqUnsuccessfulJobException: If the job failed or has been + canceled or deleted. + ~gss.SuperstaqServerException: If unable to get the results from the API. TimeoutError: If no results are available in the provided timeout interval. """ time_waited_seconds: float = 0.0 diff --git a/cirq-superstaq/cirq_superstaq/ops/qubit_gates.py b/cirq-superstaq/cirq_superstaq/ops/qubit_gates.py index 73982cb03..3f196b0ed 100644 --- a/cirq-superstaq/cirq_superstaq/ops/qubit_gates.py +++ b/cirq-superstaq/cirq_superstaq/ops/qubit_gates.py @@ -652,7 +652,7 @@ def parallel_gates_operation(*ops: cirq.Operation) -> cirq.Operation: ops: Operations to pack into a single `ParallelGates` operation. Returns: - ParallelGates(op.gate, op2.gate, ...).on(*op.qubits, *op2.qubits, ...) + `ParallelGates(op.gate, op2.gate, ...).on(*op.qubits, *op2.qubits, ...)` Raises: ValueError: If the operation has no `.gate` attribute. @@ -870,15 +870,20 @@ def _from_json_dict_(cls, **_kwargs: object) -> IXGate: return cls() -CR = ZX = ZXPowGate() # standard CR is a full turn of ZX, i.e. exponent = 1 +# (Sphinx doesn't like double = on one line) +ZX = ZXPowGate() +CR = ZX # standard CR is a full turn of ZX, i.e. exponent = 1 IX = IXGate() # iToffoli gate ICCX = IX.controlled(2, [1, 1]) + # Open-control iToffoli gate -AQTICCX = AQTITOFFOLI = IX.controlled(2, [0, 0]) +# (Sphinx doesn't like double = on one line) +AQTITOFFOLI = IX.controlled(2, [0, 0]) +AQTICCX = AQTITOFFOLI @cirq.value_equality(approximate=True) diff --git a/cirq-superstaq/cirq_superstaq/service.py b/cirq-superstaq/cirq_superstaq/service.py index b5e85e002..3eb8896d1 100644 --- a/cirq-superstaq/cirq_superstaq/service.py +++ b/cirq-superstaq/cirq_superstaq/service.py @@ -341,7 +341,7 @@ def create_job( Raises: ValueError: If there are no measurements in `circuits`. - SuperstaqServerException: If there was an error accessing the API. + ~gss.SuperstaqServerException: If there was an error accessing the API. """ css.validation.validate_cirq_circuits(circuits, require_measurements=True) serialized_circuits = css.serialization.serialize_circuits(circuits) @@ -373,7 +373,7 @@ def get_job(self, job_id: str) -> css.job.Job: A `css.Job` which can be queried for status or results. Raises: - SuperstaqServerException: If there was an error accessing the API. + ~gss.SuperstaqServerException: If there was an error accessing the API. """ return css.job.Job(client=self._client, job_id=job_id) @@ -387,7 +387,7 @@ def resource_estimate( target: String of target representing target device. Returns: - `ResourceEstimate`(s) containing resource costs (after compilation). + ResourceEstimate(s) containing resource costs (after compilation). """ css.validation.validate_cirq_circuits(circuits) circuit_is_list = not isinstance(circuits, cirq.Circuit) @@ -588,10 +588,10 @@ def qscout_compile( programs (strings). References: - [1] S. M. Clark et al., *Engineering the Quantum Scientific Computing Open User - Testbed*, IEEE Transactions on Quantum Engineering Vol. 2, 3102832 (2021). + [1] S. M. Clark et al., Engineering the Quantum Scientific Computing Open User + Testbed, IEEE Transactions on Quantum Engineering Vol. 2, 3102832 (2021). https://doi.org/10.1109/TQE.2021.3096480. - [2] B. Morrison, et al., *Just Another Quantum Assembly Language (Jaqal)*, 2020 IEEE + [2] B. Morrison, et al., Just Another Quantum Assembly Language (Jaqal), 2020 IEEE International Conference on Quantum Computing and Engineering (QCE), 402-408 (2020). https://arxiv.org/abs/2008.08042. @@ -694,7 +694,7 @@ def cq_compile( kwargs: Other desired `cq_compile` options. Returns: - Object whose .circuit(s) attribute contains the compiled `cirq.Circuit`(s). + Object whose .circuit(s) attribute contains the compiled cirq.Circuit(s). Raises: ValueError: If `target` is not a valid CQ target. @@ -727,12 +727,16 @@ def ibmq_compile( targets. Superstaq currently supports the following dynamical decoupling strategies: + * "standard": Places a single DD sequence in each idle window. + * "syncopated": Places DD pulses at fixed time intervals, alternating between pulses on - neighboring qubits in order to mitigate parasitic ZZ coupling errors. + neighboring qubits in order to mitigate parasitic ZZ coupling errors. + * "adaptive" (default): Dynamically spaces DD pulses across idle windows with awareness of - neighboring qubits to achieve the parasitic ZZ coupling mitigation of the "syncopated" - strategy with fewer pulses and less discretization error. + neighboring qubits to achieve the parasitic ZZ coupling mitigation of the "syncopated" + strategy with fewer pulses and less discretization error. + See https://superstaq.readthedocs.io/en/latest/optimizations/ibm/ibmq_dd_strategies_qss.html for an example of each strategy. @@ -745,7 +749,7 @@ def ibmq_compile( kwargs: Other desired compile options. Returns: - Object whose .circuit(s) attribute contains the compiled `cirq.Circuit`(s), and whose + Object whose .circuit(s) attribute contains the compiled cirq.Circuit(s), and whose .pulse_gate_circuit(s) attribute contains the corresponding pulse schedule(s) (when available). @@ -873,7 +877,7 @@ def submit_dfe( Raises: ValueError: If `circuit` is not a valid `cirq.Circuit`. - SuperstaqServerException: If there was an error accessing the API. + ~gss.SuperstaqServerException: If there was an error accessing the API. """ circuit_1 = rho_1[0] circuit_2 = rho_2[0] @@ -912,7 +916,8 @@ def process_dfe(self, ids: list[str]) -> float: Raises: ValueError: If `ids` is not of size two. - SuperstaqServerException: If there was an error accesing the API or the jobs submitted + ~gss.SuperstaqServerException: If there was an error accessing the API or + the jobs submitted through `submit_dfe` have not finished running. """ return self._client.process_dfe(ids) @@ -934,7 +939,7 @@ def submit_aces( ) -> str: """Submits the jobs to characterize `target` through the ACES protocol. - The following gate eigenvalues are eestimated. For each qubit in the device, we consider + The following gate eigenvalues are estimated. For each qubit in the device, we consider six Clifford gates. These are given by the XZ maps: XZ, ZX, -YZ, -XY, ZY, YX. For each of these gates, three eigenvalues are returned (X, Y, Z, in that order). Then, the two-qubit gate considered here is the CZ in linear connectivity (each qubit n with n + 1). For this @@ -976,7 +981,7 @@ def submit_aces( Raises: ValueError: If the target or noise model is not valid. - SuperstaqServerException: If the request fails. + ~gss.SuperstaqServerException: If the request fails. """ noise_dict: dict[str, object] = {} if isinstance(noise, str): @@ -1047,7 +1052,7 @@ def submit_cb( Raises: ValueError: If the target or noise model is not valid. - SuperstaqServerException: If the request fails. + ~gss.SuperstaqServerException: If the request fails. """ noise_dict: dict[str, object] = {} @@ -1085,7 +1090,7 @@ def process_cb(self, job_id: str, counts: list[dict[str, int]] | None = None) -> A dict containing the Cycle Benchmarking process data. Raises: - SuperstaqServerException: If the request fails. + ~gss.SuperstaqServerException: If the request fails. """ serialized_counts = cirq.to_json(counts) if counts else None cb_data = self._client.process_cb(job_id, serialized_counts) diff --git a/docs/source/conf.py b/docs/source/conf.py index 6b31d77c9..b0fc44a5c 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -2,6 +2,8 @@ # # For the full list of built-in configuration values, see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html +# pylint: disable=missing-function-docstring,missing-class-docstring,unused-argument +# mypy: disable-error-code="no-untyped-def" # -- Path setup -------------------------------------------------------------- from __future__ import annotations @@ -23,11 +25,11 @@ extensions = [ "nbsphinx", - "sphinx.ext.autodoc", - "sphinx.ext.autosummary", "sphinx.ext.mathjax", # math rendering in html "sphinx.ext.napoleon", # allows google- and numpy- style docstrings "IPython.sphinxext.ipython_console_highlighting", + "autoapi.extension", + "sphinx.ext.autodoc", ] # since our notebooks can involve network I/O (or even costing $), we don't want them to be @@ -36,20 +38,35 @@ # In addition, we set the mathjax path to v3, which allows \ket{} (and other commands) to render mathjax_path = "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" -autosummary_generate = True +autosummary_generate = False templates_path = ["_templates"] -# Using `modules` in index.rst gets the first package and ignores additional included packages. -# Listing out modules explicitly causes building docs to throw error looking for `modules.rst`, -# so add to excluded search patterns as per suggestion here: https://stackoverflow.com/a/15438962 -exclude_patterns: list[str] = [ - "modules.rst", - "setup.rst", - "general_superstaq.check.rst", - "cirq_superstaq.ops.rst", +autoapi_dirs = [ + "../../cirq-superstaq/cirq_superstaq", + "../../general-superstaq/general_superstaq", + "../../qiskit-superstaq/qiskit_superstaq", + "../../supermarq-benchmarks/supermarq", +] +autoapi_type = "python" + +autoapi_options = [ + "members", + "undoc-members", + "show-inheritance", + "show-module-summary", + "imported-members", ] +autoapi_ignore = ["*_test.py", "*/checks/*.py", "*conftest.py"] + +exclude_patterns = [ + "autoapi/index.rst", + "optimizations/ibm/ibmq_dd_strategies_qss.ipynb", + "apps/supermarq/examples/qre-challenge/grovers-ksat.ipynb", +] + +autoapi_member_order = "groupwise" # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output @@ -65,3 +82,15 @@ "css/docs-superstaq.css", ] html_favicon = "_static/logos/Infleqtion_logo.png" + + +# Replace common aliases (gss, css, qss) in docstrings. +def autodoc_process_docstring(app, what, name, obj, options, lines): + for i in range(len(lines)): + lines[i] = lines[i].replace("gss.", "general_superstaq.") + lines[i] = lines[i].replace("css.", "cirq_superstaq.") + lines[i] = lines[i].replace("qss.", "qiskit_superstaq.") + + +def setup(app): + app.connect("autodoc-process-docstring", autodoc_process_docstring) diff --git a/docs/source/index.rst b/docs/source/index.rst index e23ef02ee..ff73a8908 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -76,8 +76,9 @@ Learn more about Superstaq `here `_. To co .. toctree:: :maxdepth: 1 :hidden: - :caption: Clients + :caption: API Reference - cirq_superstaq - qiskit_superstaq - general_superstaq \ No newline at end of file + autoapi/cirq_superstaq/index + autoapi/general_superstaq/index + autoapi/qiskit_superstaq/index + autoapi/supermarq/index \ No newline at end of file diff --git a/docs/source/optimizations/ibm/ibm.rst b/docs/source/optimizations/ibm/ibm.rst index 67146e10b..9419b4e2b 100644 --- a/docs/source/optimizations/ibm/ibm.rst +++ b/docs/source/optimizations/ibm/ibm.rst @@ -11,7 +11,6 @@ Below, you will find links to identical tutorials that demonstrate Superstaq for ibmq_compile_qss ibmq_compile_css - ibmq_dd_strategies_qss ibmq_dd References diff --git a/general-superstaq/general_superstaq/service.py b/general-superstaq/general_superstaq/service.py index 55f100489..e36a50090 100644 --- a/general-superstaq/general_superstaq/service.py +++ b/general-superstaq/general_superstaq/service.py @@ -89,7 +89,7 @@ def update_user_balance(self, email: str, balance: float) -> str: balance: The new balance. Raises: - SuperstaqException: If requested balance exceeds the limit. + superstaq.SuperstaqException: If requested balance exceeds the limit. Returns: String containing status of update (whether or not it failed). @@ -437,7 +437,7 @@ def submit_aces( Raises: ValueError: If the target or noise model are not valid. - SuperstaqServerException: If the request fails. + ~gss.SuperstaqServerException: If the request fails. """ noise_dict: dict[str, object] = {} if noise: diff --git a/general-superstaq/general_superstaq/superstaq_client.py b/general-superstaq/general_superstaq/superstaq_client.py index 936337210..b972a66b7 100644 --- a/general-superstaq/general_superstaq/superstaq_client.py +++ b/general-superstaq/general_superstaq/superstaq_client.py @@ -162,7 +162,7 @@ def create_job( about the job, but does contain the job id. Raises: - gss.SuperstaqServerException: if the request fails. + ~gss.SuperstaqServerException: if the request fails. """ gss.validation.validate_target(target) gss.validation.validate_integer_param(repetitions) @@ -193,7 +193,7 @@ def cancel_jobs( A list of the job ids of the jobs that successfully cancelled. Raises: - SuperstaqServerException: For other API call failures. + ~gss.SuperstaqServerException: For other API call failures. """ json_dict: dict[str, str | Sequence[str]] = { "job_ids": job_ids, @@ -218,7 +218,7 @@ def fetch_jobs( The json body of the response as a dict. Raises: - SuperstaqServerException: For other API call failures. + ~gss.SuperstaqServerException: For other API call failures. """ json_dict: dict[str, Any] = { @@ -258,7 +258,7 @@ def get_user_info( parameters are used this dictionary will have length 1. Raises: - SuperstaqServerException: If the server returns an empty response. + ~gss.SuperstaqServerException: If the server returns an empty response. """ query = {} if name is not None: @@ -483,7 +483,7 @@ def submit_dfe( Raises: ValueError: If any of the targets passed are not valid. - SuperstaqServerException: if the request fails. + ~gss.SuperstaqServerException: if the request fails. """ gss.validation.validate_target(target_1) gss.validation.validate_target(target_2) @@ -513,7 +513,7 @@ def process_dfe(self, job_ids: list[str]) -> float: Raises: ValueError: If `job_ids` is not of size two. - SuperstaqServerException: If the request fails. + ~gss.SuperstaqServerException: If the request fails. """ if len(job_ids) != 2: raise ValueError("`job_ids` must contain exactly two job ids.") @@ -558,7 +558,7 @@ def submit_aces( Raises: ValueError: If the target or noise model is not valid. - SuperstaqServerException: If the request fails. + ~gss.SuperstaqServerException: If the request fails. """ gss.validation.validate_target(target) @@ -626,7 +626,7 @@ def submit_cb( Raises: ValueError: If the target or noise model is not valid. - SuperstaqServerException: If the request fails. + ~gss.SuperstaqServerException: If the request fails. """ gss.validation.validate_target(target) @@ -775,8 +775,8 @@ def _handle_status_codes(self, response: requests.Response) -> None: response: The `requests.Response` to get the status codes from. Raises: - gss.SuperstaqServerException: If unauthorized by Superstaq API. - gss.SuperstaqServerException: If an error has occurred in making a request + ~gss.SuperstaqServerException: If unauthorized by Superstaq API. + ~gss.SuperstaqServerException: If an error has occurred in making a request to the Superstaq API. """ @@ -827,7 +827,7 @@ def _prompt_accept_terms_of_use(self) -> None: """Prompts terms of use. Raises: - gss.SuperstaqServerException: If terms of use are not accepted. + ~gss.SuperstaqServerException: If terms of use are not accepted. """ message = ( "Acceptance of the Terms of Use (superstaq.infleqtion.com/terms_of_use)" @@ -849,7 +849,8 @@ def _make_request(self, request: Callable[[], requests.Response]) -> requests.Re request: A function that returns a `requests.Response`. Raises: - SuperstaqServerException: If there was a not-retriable error from the API. + ~gss.SuperstaqServerException: If there was a not-retriable error from + the API. TimeoutError: If the requests retried for more than `max_retry_seconds`. Returns: diff --git a/qiskit-superstaq/qiskit_superstaq/conftest.py b/qiskit-superstaq/qiskit_superstaq/conftest.py index ccbe317c6..32a0baae8 100644 --- a/qiskit-superstaq/qiskit_superstaq/conftest.py +++ b/qiskit-superstaq/qiskit_superstaq/conftest.py @@ -16,13 +16,13 @@ def get_targets(self, **kwargs: bool | None) -> list[gss.typing.Target]: kwargs: Optional flags to restrict/filter returned targets. - simulator: Optional flag to restrict the list of targets to (non-) simulators. - supports_submit: Optional boolean flag to only return targets that (don't) allow - circuit submissions. + circuit submissions. - supports_submit_qubo: Optional boolean flag to only return targets that (don't) - allow qubo submissions. + allow qubo submissions. - supports_compile: Optional boolean flag to return targets that (don't) support - circuit compilation. + circuit compilation. - available: Optional boolean flag to only return targets that are (not) available - to use. + to use. - retired: Optional boolean flag to only return targets that are or are not retired. Returns: diff --git a/qiskit-superstaq/qiskit_superstaq/serialization.py b/qiskit-superstaq/qiskit_superstaq/serialization.py index a9dd0ff67..55bd7e40c 100644 --- a/qiskit-superstaq/qiskit_superstaq/serialization.py +++ b/qiskit-superstaq/qiskit_superstaq/serialization.py @@ -104,10 +104,10 @@ def to_json(val: object) -> str: def serialize_circuits(circuits: qiskit.QuantumCircuit | Sequence[qiskit.QuantumCircuit]) -> str: - """Serializes `qiskit.QuantumCircuit`(s) into a single string. + """Serializes qiskit.QuantumCircuit(s) into a single string. Args: - circuits: A `qiskit.QuantumCircuit` or list of `qiskit.QuantumCircuit`s to be serialized. + circuits: A `qiskit.QuantumCircuit` or list of `qiskit.QuantumCircuit` to be serialized. Returns: A string representing the serialized circuit(s). @@ -126,7 +126,7 @@ def serialize_circuits(circuits: qiskit.QuantumCircuit | Sequence[qiskit.Quantum def deserialize_circuits(serialized_circuits: str) -> list[qiskit.QuantumCircuit]: - """Deserializes serialized `qiskit.QuantumCircuit`(s). + """Deserializes serialized qiskit.QuantumCircuit(s). Args: serialized_circuits: String generated via `qss.serialization.serialize_circuit()`. diff --git a/qiskit-superstaq/qiskit_superstaq/superstaq_backend.py b/qiskit-superstaq/qiskit_superstaq/superstaq_backend.py index 6b0c07a5b..b22640715 100644 --- a/qiskit-superstaq/qiskit_superstaq/superstaq_backend.py +++ b/qiskit-superstaq/qiskit_superstaq/superstaq_backend.py @@ -181,7 +181,7 @@ def retrieve_job(self, job_id: str) -> qss.SuperstaqJob: A `qss.SuperstaqJob` which can be queried for status or results. Raises: - SuperstaqServerException: If there was an error accessing the API. + ~gss.SuperstaqServerException: If there was an error accessing the API. """ return qss.SuperstaqJob(self, job_id) @@ -193,7 +193,7 @@ def compile( """Compiles the given circuit(s) to the backend's native gateset. Args: - circuits: The `qiskit.QuantumCircuit`(s) to compile. + circuits: The qiskit.QuantumCircuit(s) to compile. kwargs: Other desired compile options. Returns: @@ -324,17 +324,21 @@ def ibmq_compile( """Compiles and optimizes the given circuit(s) for IBMQ devices. Superstaq currently supports the following dynamical decoupling strategies: + * "standard": Places a single DD sequence in each idle window. + * "syncopated": Places DD pulses at fixed time intervals, alternating between pulses on - neighboring qubits in order to mitigate parasitic ZZ coupling errors. + neighboring qubits in order to mitigate parasitic ZZ coupling errors. + * "adaptive" (default): Dynamically spaces DD pulses across idle windows with awareness of - neighboring qubits to achieve the parasitic ZZ coupling mitigation of the "syncopated" - strategy with fewer pulses and less discretization error. + neighboring qubits to achieve the parasitic ZZ coupling mitigation of the "syncopated" + strategy with fewer pulses and less discretization error. + See https://superstaq.readthedocs.io/en/latest/optimizations/ibm/ibmq_dd_strategies_qss.html for an example of each strategy. Args: - circuits: The `qiskit.QuantumCircuit`(s) to compile. + circuits: The qiskit.QuantumCircuit(s) to compile. dynamical_decoupling: Applies dynamical decoupling optimization to circuit(s). dd_strategy: Method to use for placing dynamical decoupling operations; should be either "standard", "syncopated", or "adaptive" (default). See above. @@ -377,10 +381,10 @@ def qscout_compile( Jaqal [2] programs (strings). References: - [1] S. M. Clark et al., *Engineering the Quantum Scientific Computing Open User - Testbed*, IEEE Transactions on Quantum Engineering Vol. 2, 3102832 (2021). + [1] S. M. Clark et al., Engineering the Quantum Scientific Computing Open User + Testbed, IEEE Transactions on Quantum Engineering Vol. 2, 3102832 (2021). https://doi.org/10.1109/TQE.2021.3096480. - [2] B. Morrison, et al., *Just Another Quantum Assembly Language (Jaqal)*, 2020 IEEE + [2] B. Morrison, et al., Just Another Quantum Assembly Language (Jaqal), 2020 IEEE International Conference on Quantum Computing and Engineering (QCE), 402-408 (2020). https://arxiv.org/abs/2008.08042. @@ -462,7 +466,7 @@ def cq_compile( """Compiles and optimizes the given circuit(s) for CQ devices. Args: - circuits: The `qiskit.QuantumCircuit`(s) to compile. + circuits: The qiskit.QuantumCircuit(s) to compile. grid_shape: Optional fixed dimensions for the rectangular qubit grid (by default the actual qubit layout will be pulled from the hardware provider). control_radius: The radius with which qubits remain connected @@ -510,7 +514,7 @@ def resource_estimate( circuits: The circuit(s) used during resource estimation. Returns: - `ResourceEstimate`(s) containing resource costs (after compilation) for running + ResourceEstimate(s) containing resource costs (after compilation) for running circuit(s) on this backend. """ request_json = self._get_compile_request_json(circuits) @@ -582,7 +586,7 @@ def submit_aces( Raises: AssertionError: If the weights are not an Iterable type. ValueError: If the target or noise model is not valid. - SuperstaqServerException: If the request fails. + ~gss.SuperstaqServerException: If the request fails. """ noise_dict: dict[str, object] = {} if noise: diff --git a/qiskit-superstaq/qiskit_superstaq/superstaq_job.py b/qiskit-superstaq/qiskit_superstaq/superstaq_job.py index 953cadb7a..57a9875d3 100644 --- a/qiskit-superstaq/qiskit_superstaq/superstaq_job.py +++ b/qiskit-superstaq/qiskit_superstaq/superstaq_job.py @@ -168,8 +168,10 @@ def _check_if_stopped(self) -> None: raises an exception if it is. Raises: - gss.SuperstaqUnsuccessfulJobException: If the job has been cancelled or has failed. - gss.SuperstaqServerException: If unable to get the status of the job from the API. + ~gss.SuperstaqUnsuccessfulJobException: If the job has been cancelled or + has failed. + ~gss.SuperstaqServerException: If unable to get the status of the job + from the API. """ if self._overall_status in ("Cancelled", "Failed"): raise gss.superstaq_exceptions.SuperstaqUnsuccessfulJobException( @@ -184,8 +186,8 @@ def cancel(self, index: int | None = None, **kwargs: object) -> None: kwargs: Extra options needed to fetch jobs. Raises: - gss.SuperstaqServerException: If unable to get the status of the job from the API - or cancellations were unsuccessful. + ~gss.SuperstaqServerException: If unable to get the status of the job + from the API or cancellations were unsuccessful. """ job_ids = self._job_id.split(",") ids_to_cancel = [job_ids[index]] if index else job_ids diff --git a/qiskit-superstaq/qiskit_superstaq/superstaq_provider.py b/qiskit-superstaq/qiskit_superstaq/superstaq_provider.py index 39e8fef50..9aaa3ebff 100644 --- a/qiskit-superstaq/qiskit_superstaq/superstaq_provider.py +++ b/qiskit-superstaq/qiskit_superstaq/superstaq_provider.py @@ -174,7 +174,7 @@ def resource_estimate( target: A string containing the name of a target backend. Returns: - `ResourceEstimate`(s) containing resource costs (after compilation) for running + ResourceEstimate(s) containing resource costs (after compilation) for running circuit(s) on a backend. """ return self.get_backend(target).resource_estimate(circuits) @@ -317,12 +317,16 @@ def ibmq_compile( """Returns pulse schedule(s) for the given qiskit circuit(s) and target. Superstaq currently supports the following dynamical decoupling strategies: + * "standard": Places a single DD sequence in each idle window. + * "syncopated": Places DD pulses at fixed time intervals, alternating between pulses on - neighboring qubits in order to mitigate parasitic ZZ coupling errors. + neighboring qubits in order to mitigate parasitic ZZ coupling errors. + * "adaptive" (default): Dynamically spaces DD pulses across idle windows with awareness of - neighboring qubits to achieve the parasitic ZZ coupling mitigation of the "syncopated" - strategy with fewer pulses and less discretization error. + neighboring qubits to achieve the parasitic ZZ coupling mitigation of the "syncopated" + strategy with fewer pulses and less discretization error. + See https://superstaq.readthedocs.io/en/latest/optimizations/ibm/ibmq_dd_strategies_qss.html for an example of each strategy. @@ -368,10 +372,10 @@ def qscout_compile( Jaqal [2] programs (strings). References: - [1] S. M. Clark et al., *Engineering the Quantum Scientific Computing Open User - Testbed*, IEEE Transactions on Quantum Engineering Vol. 2, 3102832 (2021). + [1] S. M. Clark et al., Engineering the Quantum Scientific Computing Open User + Testbed, IEEE Transactions on Quantum Engineering Vol. 2, 3102832 (2021). https://doi.org/10.1109/TQE.2021.3096480. - [2] B. Morrison, et al., *Just Another Quantum Assembly Language (Jaqal)*, 2020 IEEE + [2] B. Morrison, et al., Just Another Quantum Assembly Language (Jaqal), 2020 IEEE International Conference on Quantum Computing and Engineering (QCE), 402-408 (2020). https://arxiv.org/abs/2008.08042. @@ -468,8 +472,8 @@ def supercheq( depth: The depth of the circuits to run Supercheq on. Returns: - A tuple containing a list of `qiskit.QuantumCircuit`s and a list of corresponding - fidelity matrices. + A tuple containing a list of qiskit.QuantumCircuits and a list of corresponding + fidelity matrices. """ json_dict = self._client.supercheq(files, num_qubits, depth, "qiskit_circuits") circuits = qss.serialization.deserialize_circuits(json_dict["qiskit_circuits"]) @@ -520,7 +524,7 @@ def submit_dfe( Raises: ValueError: If `circuit` is not a valid `qiskit.QuantumCircuit`. - SuperstaqServerException: If there was an error accessing the API. + ~gss.SuperstaqServerException: If there was an error accessing the API. """ circuit_1 = rho_1[0] circuit_2 = rho_2[0] @@ -564,7 +568,7 @@ def process_dfe(self, ids: list[str]) -> float: Raises: ValueError: If `ids` is not of size two. - SuperstaqServerException: If there was an error accessing the API or the jobs submitted - through `submit_dfe` have not finished running. + ~gss.SuperstaqServerException: If there was an error accessing the API or + the jobs submitted through `submit_dfe` have not finished running. """ return self._client.process_dfe(ids) diff --git a/supermarq-benchmarks/supermarq/benchmarks/qaoa_fermionic_swap_proxy.py b/supermarq-benchmarks/supermarq/benchmarks/qaoa_fermionic_swap_proxy.py index 7cacee776..eea1ad49a 100644 --- a/supermarq-benchmarks/supermarq/benchmarks/qaoa_fermionic_swap_proxy.py +++ b/supermarq-benchmarks/supermarq/benchmarks/qaoa_fermionic_swap_proxy.py @@ -28,8 +28,10 @@ class QAOAFermionicSwapProxy(Benchmark): When a new instance of this benchmark is created, the ansatz parameters will be initialized by: - 1. Generating a random instance of an SK graph - 2. Finding approximately optimal angles (rather than random values) + + #. Generating a random instance of an SK graph + + #. Finding approximately optimal angles (rather than random values) """ def __init__(self, num_qubits: int) -> None: diff --git a/supermarq-benchmarks/supermarq/benchmarks/qaoa_vanilla_proxy.py b/supermarq-benchmarks/supermarq/benchmarks/qaoa_vanilla_proxy.py index cc81ace93..256e38a09 100644 --- a/supermarq-benchmarks/supermarq/benchmarks/qaoa_vanilla_proxy.py +++ b/supermarq-benchmarks/supermarq/benchmarks/qaoa_vanilla_proxy.py @@ -27,8 +27,10 @@ class QAOAVanillaProxy(Benchmark): When a new instance of this benchmark is created, the ansatz parameters will be initialized by: - 1. Generating a random instance of an SK graph - 2. Finding approximately optimal angles (rather than random values) + + #. Generating a random instance of an SK graph + + #. Finding approximately optimal angles (rather than random values) """ def __init__(self, num_qubits: int) -> None: diff --git a/supermarq-benchmarks/supermarq/qcvv/base_experiment.py b/supermarq-benchmarks/supermarq/qcvv/base_experiment.py index 553ffa4fe..4bc882aee 100644 --- a/supermarq-benchmarks/supermarq/qcvv/base_experiment.py +++ b/supermarq-benchmarks/supermarq/qcvv/base_experiment.py @@ -123,6 +123,7 @@ class BenchmarkingExperiment(ABC, Generic[ResultsT]): data has been collected and is ready to be analysed. .. code:: + if experiment.collect_data(): results = experiment.analyze_results(<>) @@ -139,6 +140,7 @@ class BenchmarkingExperiment(ABC, Generic[ResultsT]): Additionally it is possible to pre-compile the experimental circuits for a given device using .. code:: + experiment.prepare_experiment(<>) experiment.compile_circuits(target=<>) diff --git a/supermarq-benchmarks/supermarq/qcvv/xeb.py b/supermarq-benchmarks/supermarq/qcvv/xeb.py index 55b2f262b..7aea9b2e3 100644 --- a/supermarq-benchmarks/supermarq/qcvv/xeb.py +++ b/supermarq-benchmarks/supermarq/qcvv/xeb.py @@ -27,7 +27,7 @@ import tqdm.auto import tqdm.contrib.itertools -from supermarq.qcvv import BenchmarkingExperiment, BenchmarkingResults, Sample +from supermarq.qcvv.base_experiment import BenchmarkingExperiment, BenchmarkingResults, Sample @dataclass @@ -95,8 +95,6 @@ class XEB(BenchmarkingExperiment[XEBResults]): cycles made up of two randomly selected single qubit phased XZ gates and a constant two qubit gate. This is illustrated as follows: - .. image:: ../../superstaq/qcvv/XEB_Random_Circuit.png - For each randomly generated circuit, with a given number of cycle, we compare the simulated state probabilities, :math:`p(x)` with those achieved by running the circuit on a given target, :math:`\hat{p}(x)`. The fidelity of a circuit containing :math:`d` diff --git a/supermarq-benchmarks/supermarq/simulation.py b/supermarq-benchmarks/supermarq/simulation.py index 17a134c44..833d337fc 100644 --- a/supermarq-benchmarks/supermarq/simulation.py +++ b/supermarq-benchmarks/supermarq/simulation.py @@ -9,9 +9,12 @@ def get_ideal_counts(circuit: cirq.Circuit) -> dict[str, float]: Note that the qubits in the returned bitstrings are in big-endian order. For example, for a circuit defined on qubits + .. code:: + q0 ------ q1 ------ q2 ------ + the bitstrings are written as `q0q1q2`. Args: diff --git a/supermarq-benchmarks/supermarq/stabilizers.py b/supermarq-benchmarks/supermarq/stabilizers.py index 5bb2d7ff1..afa2129f7 100644 --- a/supermarq-benchmarks/supermarq/stabilizers.py +++ b/supermarq-benchmarks/supermarq/stabilizers.py @@ -49,12 +49,14 @@ def get_stabilizer(self) -> npt.NDArray[np.uint8]: represented as a (2*N, M) matrix. For instance, YYI, XXY, IYZ would be represented by - [[1, 0, 0], ======== - [1, 0, 1], Z matrix (top half) - [0, 1, 1], ======== - [1, 1, 0], ======== - [1, 1, 1], X matrix (bottom half) - [0, 1, 0] ======== + .. code:: + + [[1, 0, 0], ======== + [1, 0, 1], Z matrix (top half) + [0, 1, 1], ======== + [1, 1, 0], ======== + [1, 1, 1], X matrix (bottom half) + [0, 1, 0] ======== Returns: The current stabilizer matrix.