def required_predicates(self) -> List[Predicate]: preds = [ NoSymbolsPredicate(), GateSetPredicate(_GATE_SET), ] if not self._MACHINE_DEBUG: assert self.device is not None preds.append(MaxNQubitsPredicate(len(self.device.nodes))) return preds
def required_predicates(self) -> List[Predicate]: preds = [ NoClassicalControlPredicate(), NoFastFeedforwardPredicate(), NoMidMeasurePredicate(), NoSymbolsPredicate(), GateSetPredicate(ionq_gates), MaxNQubitsPredicate(self._max_n_qubits), ] return preds
def required_predicates(self) -> List[Predicate]: preds = [ NoClassicalControlPredicate(), NoFastFeedforwardPredicate(), NoMidMeasurePredicate(), NoSymbolsPredicate(), GateSetPredicate({ OpType.Rx, OpType.Ry, OpType.XXPhase, OpType.Measure, OpType.Barrier }), ] if self._max_n_qubits is not None: preds.append(MaxNQubitsPredicate(self._max_n_qubits)) return preds
def __init__( self, local: bool = False, s3_bucket: str = "", s3_folder: str = "", device_type: str = "quantum-simulator", provider: str = "amazon", device: str = "sv1", ): """ Construct a new braket backend. If `local=True`, other parameters are ignored. :param local: use simulator running on local machine :param s3_bucket: name of S3 bucket to store results :param s3_folder: name of folder ("key") in S3 bucket to store results in :param device_type: device type from device ARN (e.g. "qpu") :param provider: provider name from device ARN (e.g. "ionq", "rigetti", ...) :paran device: device name from device ARN (e.g. "ionQdevice", "Aspen-8", ...) """ super().__init__() if local: self._device = LocalSimulator() self._device_type = _DeviceType.LOCAL else: self._device = AwsDevice( "arn:aws:braket:::" + "/".join(["device", device_type, provider, device])) self._s3_dest = (s3_bucket, s3_folder) aws_device_type = self._device.type if aws_device_type == AwsDeviceType.SIMULATOR: self._device_type = _DeviceType.SIMULATOR elif aws_device_type == AwsDeviceType.QPU: self._device_type = _DeviceType.QPU else: raise ValueError(f"Unsupported device type {aws_device_type}") props = self._device.properties.dict() paradigm = props["paradigm"] n_qubits = paradigm["qubitCount"] connectivity_graph = None # None means "fully connected" if self._device_type == _DeviceType.QPU: connectivity = paradigm["connectivity"] if connectivity["fullyConnected"]: self._all_qubits: List = list(range(n_qubits)) else: connectivity_graph = connectivity["connectivityGraph"] # Convert strings to ints connectivity_graph = dict( (int(k), [int(v) for v in l]) for k, l in connectivity_graph.items()) self._all_qubits = sorted(connectivity_graph.keys()) if n_qubits < len(self._all_qubits): # This can happen, at least on rigetti devices, and causes errors. # As a kludgy workaround, remove some qubits from the architecture. self._all_qubits = self._all_qubits[:( n_qubits - len(self._all_qubits))] connectivity_graph = dict( (k, [v for v in l if v in self._all_qubits]) for k, l in connectivity_graph.items() if k in self._all_qubits) self._characteristics: Optional[Dict] = props["provider"] else: self._all_qubits = list(range(n_qubits)) self._characteristics = None device_info = props["action"][DeviceActionType.JAQCD] supported_ops = set(op.lower() for op in device_info["supportedOperations"]) supported_result_types = device_info["supportedResultTypes"] self._result_types = set() for rt in supported_result_types: rtname = rt["name"] rtminshots = rt["minShots"] rtmaxshots = rt["maxShots"] self._result_types.add(rtname) if rtname == "StateVector": self._supports_state = True # Always use n_shots = 0 for StateVector elif rtname == "Amplitude": pass # Always use n_shots = 0 for Amplitude elif rtname == "Probability": self._probability_min_shots = rtminshots self._probability_max_shots = rtmaxshots elif rtname == "Expectation": self._supports_expectation = True self._expectation_allows_nonhermitian = False self._expectation_min_shots = rtminshots self._expectation_max_shots = rtmaxshots elif rtname == "Sample": self._supports_shots = True self._supports_counts = True self._sample_min_shots = rtminshots self._sample_max_shots = rtmaxshots elif rtname == "Variance": self._variance_min_shots = rtminshots self._variance_max_shots = rtmaxshots self._multiqs = set() self._singleqs = set() if not {"cnot", "rx", "rz"} <= supported_ops: # This is so that we can define RebaseCustom without prior knowledge of the # gate set. We could do better than this, by having a few different options # for the CX- and tk1-replacement circuits. But it seems all existing # backends support these gates. raise NotImplementedError( "Device must support cnot, rx and rz gates.") for t in supported_ops: tkt = _gate_types[t] if tkt is not None: if t in _multiq_gate_types: if self._device_type == _DeviceType.QPU and t in [ "ccnot", "cswap" ]: # FullMappingPass can't handle 3-qubit gates, so ignore them. continue self._multiqs.add(tkt) else: self._singleqs.add(tkt) self._req_preds = [ NoClassicalControlPredicate(), NoFastFeedforwardPredicate(), NoMidMeasurePredicate(), NoSymbolsPredicate(), GateSetPredicate(self._multiqs | self._singleqs), MaxNQubitsPredicate(n_qubits), ] if connectivity_graph is None: arch = FullyConnected(n_qubits) else: arch = Architecture([(k, v) for k, l in connectivity_graph.items() for v in l]) if self._device_type == _DeviceType.QPU: assert self._characteristics is not None node_errs = {} edge_errs = {} schema = self._characteristics["braketSchemaHeader"] if schema == IONQ_SCHEMA: fid = self._characteristics["fidelity"] mean_1q_err = 1 - fid["1Q"]["mean"] mean_2q_err = 1 - fid["2Q"]["mean"] err_1q_cont = QubitErrorContainer(self._singleqs) for optype in self._singleqs: err_1q_cont.add_error((optype, mean_1q_err)) err_2q_cont = QubitErrorContainer(self._multiqs) for optype in self._multiqs: err_2q_cont.add_error((optype, mean_2q_err)) for node in arch.nodes: node_errs[node] = err_1q_cont for coupling in arch.coupling: edge_errs[coupling] = err_2q_cont elif schema == RIGETTI_SCHEMA: specs = self._characteristics["specs"] specs1q, specs2q = specs["1Q"], specs["2Q"] for node in arch.nodes: nodespecs = specs1q[f"{node.index[0]}"] err_1q_cont = QubitErrorContainer(self._singleqs) for optype in self._singleqs: err_1q_cont.add_error( (optype, 1 - nodespecs.get("f1QRB", 1))) err_1q_cont.add_readout(nodespecs.get("fRO", 1)) node_errs[node] = err_1q_cont for coupling in arch.coupling: node0, node1 = coupling n0, n1 = node0.index[0], node1.index[0] couplingspecs = specs2q[f"{min(n0,n1)}-{max(n0,n1)}"] err_2q_cont = QubitErrorContainer({OpType.CZ}) err_2q_cont.add_error( (OpType.CZ, 1 - couplingspecs.get("fCZ", 1))) edge_errs[coupling] = err_2q_cont self._tket_device = Device(node_errs, edge_errs, arch) if connectivity_graph is not None: self._req_preds.append(ConnectivityPredicate( self._tket_device)) else: self._tket_device = None self._rebase_pass = RebaseCustom( self._multiqs, Circuit(), self._singleqs, lambda a, b, c: Circuit(1).Rz(c, 0).Rx(b, 0).Rz(a, 0), ) self._squash_pass = SquashCustom( self._singleqs, lambda a, b, c: Circuit(1).Rz(c, 0).Rx(b, 0).Rz(a, 0), )