13
13
# limitations under the License.
14
14
15
15
import dataclasses
16
- from typing import Union , Optional
16
+ from typing import cast , Optional , Sequence , Union
17
17
18
18
import cirq
19
19
20
- from cirq_google import (
21
- PhasedFSimEngineSimulator ,
22
- ProcessorSampler ,
23
- Sycamore ,
24
- SQRT_ISWAP_INV_PARAMETERS ,
25
- PhasedFSimCharacterization ,
26
- get_engine ,
20
+ from cirq_google import ProcessorSampler , get_engine
21
+ from cirq_google . engine import (
22
+ AbstractEngine ,
23
+ AbstractProcessor ,
24
+ AbstractLocalProcessor ,
25
+ create_noiseless_virtual_engine_from_latest_templates ,
26
+ EngineProcessor ,
27
27
)
28
28
29
29
30
30
@dataclasses .dataclass
31
31
class QCSObjectsForNotebook :
32
+ """All the objects you might need to run a notbook with QCS.
33
+
34
+ Contains an (Abstract) Engine, Processor, Device, and Sampler,
35
+ as well as associated meta-data signed_in, processor_id, and project_id.
36
+
37
+ This removes the need for boiler plate in notebooks, and provides a
38
+ central place to handle the various environments (testing vs production),
39
+ (stand-alone vs colab vs jupyter).
40
+ """
41
+
42
+ engine : AbstractEngine
43
+ processor : AbstractProcessor
32
44
device : cirq .Device
33
- sampler : Union [ PhasedFSimEngineSimulator , ProcessorSampler ]
45
+ sampler : ProcessorSampler
34
46
signed_in : bool
35
-
36
- @property
37
- def is_simulator (self ):
38
- return isinstance (self .sampler , PhasedFSimEngineSimulator )
47
+ processor_id : Optional [str ]
48
+ project_id : Optional [str ]
49
+ is_simulator : bool
39
50
40
51
41
- # Disable missing-raises-doc lint check, since pylint gets confused
42
- # by exceptions that are raised and caught within this function.
43
- # pylint: disable=missing-raises-doc
44
52
def get_qcs_objects_for_notebook (
45
- project_id : Optional [str ] = None , processor_id : Optional [str ] = None
46
- ) -> QCSObjectsForNotebook : # pragma: nocover
47
- """Authenticates on Google Cloud, can return a Device and Simulator.
53
+ project_id : Optional [str ] = None , processor_id : Optional [str ] = None , virtual = False
54
+ ) -> QCSObjectsForNotebook :
55
+ """Authenticates on Google Cloud and returns Engine related objects.
56
+
57
+ This function will authenticate to Google Cloud and attempt to
58
+ instantiate an Engine object. If it does not succeed, it will instead
59
+ return a virtual AbstractEngine that is backed by a noisy simulator.
60
+ This function is designed for maximum versatility and
61
+ to work in colab notebooks, as a stand-alone, and in tests.
62
+
63
+ Note that, if you are using this to connect to QCS and do not care about
64
+ the added versatility, you may want to use `cirq_google.get_engine()` or
65
+ `cirq_google.Engine()` instead to guarantee the use of a production instance
66
+ and to avoid accidental use of a noisy simulator.
48
67
49
68
Args:
50
69
project_id: Optional explicit Google Cloud project id. Otherwise,
@@ -53,9 +72,14 @@ def get_qcs_objects_for_notebook(
53
72
personal project IDs in shared code.
54
73
processor_id: Engine processor ID (from Cloud console or
55
74
``Engine.list_processors``).
75
+ virtual: If set to True, will create a noisy virtual Engine instead.
76
+ This is useful for testing and simulation.
56
77
57
78
Returns:
58
- An instance of DeviceSamplerInfo.
79
+ An instance of QCSObjectsForNotebook which contains all the objects .
80
+
81
+ Raises:
82
+ ValueError: if processor_id is not specified and no processors are available.
59
83
"""
60
84
61
85
# Check for Google Application Default Credentials and run
@@ -80,32 +104,46 @@ def get_qcs_objects_for_notebook(
80
104
print (f"Authentication failed: { exc } " )
81
105
82
106
# Attempt to connect to the Quantum Engine API, and use a simulator if unable to connect.
83
- sampler : Union [PhasedFSimEngineSimulator , ProcessorSampler ]
84
- try :
85
- engine = get_engine (project_id )
86
- if processor_id :
87
- processor = engine .get_processor (processor_id )
88
- else :
89
- processors = engine .list_processors ()
90
- if not processors :
91
- raise ValueError ("No processors available." )
92
- processor = processors [0 ]
93
- print (f"Available processors: { [p .processor_id for p in processors ]} " )
94
- print (f"Using processor: { processor .processor_id } " )
95
- device = processor .get_device ()
96
- sampler = processor .get_sampler ()
97
- signed_in = True
98
- except Exception as exc :
99
- print (f"Unable to connect to quantum engine: { exc } " )
100
- print ("Using a noisy simulator." )
101
- sampler = PhasedFSimEngineSimulator .create_with_random_gaussian_sqrt_iswap (
102
- mean = SQRT_ISWAP_INV_PARAMETERS ,
103
- sigma = PhasedFSimCharacterization (theta = 0.01 , zeta = 0.10 , chi = 0.01 , gamma = 0.10 , phi = 0.02 ),
104
- )
105
- device = Sycamore
107
+ if virtual :
108
+ engine : AbstractEngine = create_noiseless_virtual_engine_from_latest_templates ()
106
109
signed_in = False
107
-
108
- return QCSObjectsForNotebook (device = device , sampler = sampler , signed_in = signed_in )
109
-
110
-
111
- # pylint: enable=missing-raises-doc
110
+ is_simulator = True
111
+ else :
112
+ try :
113
+ engine = get_engine (project_id )
114
+ signed_in = True
115
+ is_simulator = False
116
+ except Exception as exc :
117
+ print (f"Unable to connect to quantum engine: { exc } " )
118
+ print ("Using a noisy simulator." )
119
+ engine = create_noiseless_virtual_engine_from_latest_templates ()
120
+ signed_in = False
121
+ is_simulator = True
122
+ if processor_id :
123
+ processor = engine .get_processor (processor_id )
124
+ else :
125
+ # All of these are either local processors or engine processors
126
+ # Either way, tell mypy they have a processor_id field.
127
+ processors = cast (
128
+ Sequence [Union [EngineProcessor , AbstractLocalProcessor ]], engine .list_processors ()
129
+ )
130
+ if not processors :
131
+ raise ValueError ("No processors available." )
132
+ processor = processors [0 ]
133
+ processor_id = processor .processor_id
134
+ print (f"Available processors: { [p .processor_id for p in processors ]} " )
135
+ print (f"Using processor: { processor_id } " )
136
+ if not project_id :
137
+ project_id = getattr (processor , 'project_id' , None )
138
+ device = processor .get_device ()
139
+ sampler = processor .get_sampler ()
140
+ return QCSObjectsForNotebook (
141
+ engine = engine ,
142
+ processor = processor ,
143
+ device = device ,
144
+ sampler = sampler ,
145
+ signed_in = signed_in ,
146
+ project_id = project_id ,
147
+ processor_id = processor_id ,
148
+ is_simulator = is_simulator ,
149
+ )
0 commit comments