microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.23.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/pip/qsharp/openqasm/_run.py

172lines · modecode

1# Copyright (c) Microsoft Corporation.
2# Licensed under the MIT License.
3
4from time import monotonic
5from typing import Any, Callable, Dict, List, Optional, Tuple, Union
6from .._fs import read_file, list_directory, resolve
7from .._http import fetch_github
8from .._native import QasmError, Output, run_qasm_program # type: ignore
9from .._qsharp import (
10 BitFlipNoise,
11 DepolarizingNoise,
12 PauliNoise,
13 PhaseFlipNoise,
14 ShotResult,
15 StateDump,
16 get_interpreter,
17 ipython_helper,
18 python_args_to_interpreter_args,
19)
20from .. import telemetry_events
21from ._ipython import display_or_print
22
23
24def run(
25 source: Union[str, Callable],
26 shots: int = 1024,
27 *args,
28 on_result: Optional[Callable[[ShotResult], None]] = None,
29 save_events: bool = False,
30 noise: Optional[
31 Union[
32 Tuple[float, float, float],
33 PauliNoise,
34 BitFlipNoise,
35 PhaseFlipNoise,
36 DepolarizingNoise,
37 ]
38 ] = None,
39 qubit_loss: Optional[float] = None,
40 as_bitstring: bool = False,
41 **kwargs: Optional[Dict[str, Any]],
42) -> List[Any]:
43 """
44 Runs the given OpenQASM program for the given number of shots.
45 Either a full program or a callable with arguments must be provided.
46 Each shot uses an independent instance of the simulator.
47
48 Args:
49 source (str): An OpenQASM program. Alternatively, a callable can be provided,
50 which must be an already imported global callable.
51 shots: The number of shots to run, Defaults to 1024.
52 *args: The arguments to pass to the callable, if one is provided.
53 on_result: A callback function that will be called with each result. Only used when a callable is provided.
54 save_events: If true, the output of each shot will be saved. If false, they will be printed. Only used when a callable is provided.
55 noise: The noise to use in simulation.
56 qubit_loss: The probability of qubit loss in simulation.
57 as_bitstring: If true, the result registers will be converted to bitstrings.
58 **kwargs: Additional keyword arguments to pass to the compilation when source program is provided.
59 - name (str): The name of the circuit. This is used as the entry point for the program.
60 - target_profile (TargetProfile): The target profile to use for code generation.
61 - search_path (Optional[str]): The optional search path for resolving file references.
62 - output_semantics (OutputSemantics, optional): The output semantics for the compilation.
63 - seed (int): The seed to use for the random number generator.
64
65 Returns:
66 values: A list of results or runtime errors. If `save_events` is true,
67 a List of ShotResults is returned.
68
69 Raises:
70 QasmError: If there is an error generating, parsing, or analyzing the OpenQASM source.
71 QSharpError: If there is an error interpreting the input.
72 ValueError: If the number of shots is less than 1.
73 ValueError: If the `on_result` and `save_events` parameters are used when running OpenQASM programs.
74 """
75
76 ipython_helper()
77
78 if shots < 1:
79 raise ValueError("The number of shots must be greater than 0.")
80
81 telemetry_events.on_run_qasm(
82 shots, noise=noise is not None, qubit_loss=qubit_loss is not None
83 )
84 start_time = monotonic()
85
86 results: List[ShotResult] = []
87
88 def on_save_events(output: Output) -> None:
89 # Append the output to the last shot's output list
90 results[-1]["events"].append(output)
91 if output.is_matrix():
92 results[-1]["matrices"].append(output)
93 elif output.is_state_dump():
94 results[-1]["dumps"].append(StateDump(output.state_dump()))
95 elif output.is_message():
96 results[-1]["messages"].append(str(output))
97
98 callable = None
99 if isinstance(source, Callable) and hasattr(source, "__global_callable"):
100 args = python_args_to_interpreter_args(args)
101 callable = source.__global_callable
102 source = None
103
104 if callable:
105 for _ in range(shots):
106 results.append(
107 {
108 "result": None,
109 "events": [],
110 "matrices": [],
111 "dumps": [],
112 "messages": [],
113 }
114 )
115 run_results = get_interpreter().run(
116 source,
117 on_save_events if save_events else display_or_print,
118 noise,
119 qubit_loss=qubit_loss,
120 callable=callable,
121 args=args,
122 )
123 results[-1]["result"] = run_results
124
125 if on_result:
126 on_result(results[-1])
127
128 if not save_events:
129 # If we are not saving events, we can just return the results
130 # as a list of results.
131 results = [result["result"] for result in results]
132 else:
133 # running the QASM program in isolation means we can't use the
134 # interpreter to run the program, so we can't cache the compilation
135 # results. This means we need to compile the program for each
136 # shot, or we push the shots into the QASM program and compile it once.
137 #
138 # This breaks the output streaming and event saving.
139 if on_result or save_events:
140 raise QasmError(
141 "The `on_result` and `save_events` parameters are not supported when running QASM programs."
142 )
143
144 # remove any entries from kwargs with a None key or None value
145 kwargs = {k: v for k, v in kwargs.items() if k is not None and v is not None}
146
147 if "search_path" not in kwargs:
148 kwargs["search_path"] = "."
149
150 kwargs["shots"] = shots
151
152 results = run_qasm_program(
153 source,
154 display_or_print,
155 noise,
156 qubit_loss,
157 read_file,
158 list_directory,
159 resolve,
160 fetch_github,
161 **kwargs,
162 )
163
164 durationMs = (monotonic() - start_time) * 1000
165 telemetry_events.on_run_qasm_end(durationMs, shots)
166
167 if as_bitstring:
168 from ._utils import as_bitstring as convert_to_bitstring
169
170 results = convert_to_bitstring(results)
171
172 return results
173