microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.18.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

source/pip/qsharp/openqasm/_run.py

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