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), )
def test_estimates() -> None: """ Check that the resource estimator gives reasonable results. """ b = QsharpEstimatorBackend() c = Circuit(3) c.H(0) c.CX(0, 1) c.CCX(0, 1, 2) c.Rx(0.3, 1) c.Ry(0.4, 2) c.Rz(1.1, 0) c.S(1) c.SWAP(0, 2) c.T(1) c.X(0) c.Y(1) c.Z(2) pbox = PauliExpBox([Pauli.X, Pauli.I, Pauli.Z], 0.25) c.add_pauliexpbox(pbox, [2, 0, 1]) b.compile_circuit(c, 0) resources = b.get_resources(c) assert resources["CNOT"] >= 1 assert resources["QubitClifford"] >= 1 assert resources["R"] >= 1 assert resources["T"] >= 1 assert resources["Depth"] >= 1 assert resources["Width"] == 3 assert resources["BorrowedWidth"] == 0
def tk_to_pyquil( tkcirc: Circuit, active_reset: bool = False, return_used_bits: bool = False ) -> Union[Program, Tuple[Program, List[Bit]]]: """ Convert a tket :py:class:`Circuit` to a :py:class:`pyquil.Program` . :param tkcirc: A circuit to be converted :return: The converted circuit """ p = Program() qregs = set() for qb in tkcirc.qubits: if len(qb.index) != 1: raise NotImplementedError( "PyQuil registers must use a single index") qregs.add(qb.reg_name) if len(qregs) > 1: raise NotImplementedError( "Cannot convert circuit with multiple quantum registers to pyQuil") creg_sizes: Dict = {} for b in tkcirc.bits: if len(b.index) != 1: raise NotImplementedError( "PyQuil registers must use a single index") if (b.reg_name not in creg_sizes) or (b.index[0] >= creg_sizes[b.reg_name]): creg_sizes.update({b.reg_name: b.index[0] + 1}) cregmap = {} for reg_name, size in creg_sizes.items(): name = reg_name if name == "c": name = "ro" quil_reg = p.declare(name, "BIT", size) cregmap.update({reg_name: quil_reg}) for sym in tkcirc.free_symbols(): p.declare(str(sym), "REAL") if active_reset: p.reset() measures = [] measured_qubits: List[Qubit] = [] used_bits: List[Bit] = [] for command in tkcirc: op = command.op optype = op.type if optype == OpType.Measure: qb = Qubit_(command.args[0].index[0]) if qb in measured_qubits: raise NotImplementedError("Cannot apply gate on qubit " + qb.__repr__() + " after measurement") bit = command.args[1] b = cregmap[bit.reg_name][bit.index[0]] measures.append(Measurement(qb, b)) measured_qubits.append(qb) used_bits.append(bit) continue elif optype == OpType.Barrier: continue # pyQuil cannot handle barriers qubits = [Qubit_(qb.index[0]) for qb in command.args] for qb in qubits: if qb in measured_qubits: raise NotImplementedError("Cannot apply gate on qubit " + qb.__repr__() + " after measurement") try: gatetype = _known_quil_gate_rev[optype] except KeyError as error: raise NotImplementedError( "Cannot convert tket Op to pyQuil gate: " + op.get_name()) from error params = [param_to_pyquil(p) for p in op.params] g = Gate(gatetype, params, qubits) p += g for m in measures: p += m if return_used_bits: return p, used_bits return p
def _tk1_to_u(a: float, b: float, c: float) -> Circuit: circ = Circuit(1) circ.add_gate(OpType.U3, [b, a - 0.5, c + 0.5], [0]) circ.add_phase(-0.5 * (a + c)) return circ
import time from pytket.circuit import Circuit, PauliExpBox from pytket.pauli import Pauli from pytket.extensions.qiskit import AerStateBackend from pytket.passes import FullPeepholeOptimise from statistics import mean, stdev nb_steps = 100 step_size = 0.01 n_qubits = [5, 10, 20, 30, 40, 50] n_runs = 10 for nb_qubits in n_qubits: data = [] for run_id in range(n_runs): # Start timer start = time.time() circ = Circuit(nb_qubits) h = 1.0 Jz = 1.0 for i in range(nb_steps): # Using Heisenberg Hamiltonian: for q in range(nb_qubits): circ.add_pauliexpbox(PauliExpBox([Pauli.X], -h * step_size), [q]) for q in range(nb_qubits - 1): circ.add_pauliexpbox( PauliExpBox([Pauli.Z, Pauli.Z], -Jz * step_size), [q, q + 1]) # Compile to gates backend = AerStateBackend()
def test_convert() -> None: circ = Circuit(4, 4) circ.H(0).CX(0, 1) circ.add_gate(OpType.noop, [1]) circ.CRz(0.5, 1, 2) circ.add_barrier([2]) circ.ZZPhase(0.3, 2, 3).CX(3, 0).Tdg(1) circ.Measure(0, 0) circ.Measure(1, 2) circ.Measure(2, 3) circ.Measure(3, 1) circ_aqt = tk_to_aqt(circ) assert json.loads(circ_aqt[1]) == [0, 3, 1, 2] assert all(gate[0] in ["X", "Y", "MS"] for gate in circ_aqt[0])
def test_convert() -> None: circ = Circuit(4) circ.H(0).CX(0, 1) circ.add_gate(OpType.noop, [1]) circ.CRz(0.5, 1, 2) circ.add_barrier([2]) circ.ZZPhase(0.3, 2, 3).CX(3, 0).Tdg(1) circ.measure_all() RebaseHQS().apply(circ) circ_hqs = circuit_to_qasm_str(circ, header="hqslib1") qasm_str = circ_hqs.split("\n")[6:-1] test = True for com in qasm_str: test &= any( com.startswith(gate) for gate in ("rz", "U1q", "ZZ", "measure", "barrier")) assert test
OpType.H, OpType.S, OpType.Sdg, OpType.T, OpType.Tdg, OpType.V, OpType.Vdg, OpType.Measure, OpType.noop, } ionq_gates = ionq_multiqs.union(ionq_singleqs) ionq_pass = RebaseCustom( ionq_multiqs, Circuit(), # cx_replacement (irrelevant) ionq_singleqs, # singleqs _from_tk1, ) # tk1_replacement ionq_gate_dict = { OpType.X: "x", OpType.Y: "y", OpType.Z: "z", OpType.Rx: "rx", OpType.Ry: "ry", OpType.Rz: "rz", OpType.H: "h", OpType.CX: "cnot", OpType.S: "s", OpType.Sdg: "si",
class CircuitBuilder: def __init__( self, qregs: List[QuantumRegister], cregs: Optional[List[ClassicalRegister]] = None, name: Optional[str] = None, phase: Optional[float] = 0.0, ): self.qregs = qregs self.cregs = [] if cregs is None else cregs self.tkc = Circuit(name=name) self.tkc.add_phase(phase) self.qregmap = {} for reg in qregs: tk_reg = self.tkc.add_q_register(reg.name, len(reg)) self.qregmap.update({reg: tk_reg}) self.cregmap = {} for reg in self.cregs: tk_reg = self.tkc.add_c_register(reg.name, len(reg)) self.cregmap.update({reg: tk_reg}) def circuit(self) -> Circuit: return self.tkc def add_qiskit_data(self, data: "QuantumCircuitData") -> None: for i, qargs, cargs in data: condition_kwargs = {} if i.condition is not None: cond_reg = self.cregmap[i.condition[0]] condition_kwargs = { "condition_bits": [cond_reg[k] for k in range(len(cond_reg))], "condition_value": i.condition[1], } if type(i) == ControlledGate: if type(i.base_gate) == qiskit_gates.RYGate: optype = OpType.CnRy else: # Maybe handle multicontrolled gates in a more general way, # but for now just do CnRy raise NotImplementedError( "qiskit ControlledGate with " + "base gate {} not implemented".format(i.base_gate)) else: optype = _known_qiskit_gate[type(i)] qubits = [ self.qregmap[qbit.register][qbit.index] for qbit in qargs ] bits = [self.cregmap[bit.register][bit.index] for bit in cargs] if optype == OpType.Unitary2qBox: u = i.to_matrix() ubox = Unitary2qBox(u) self.tkc.add_unitary2qbox(ubox, qubits[0], qubits[1], **condition_kwargs) elif optype == OpType.Barrier: self.tkc.add_barrier(qubits) elif optype in (OpType.CircBox, OpType.Custom): qregs = [QuantumRegister(i.num_qubits, "q") ] if i.num_qubits > 0 else [] cregs = ([ClassicalRegister(i.num_clbits, "c")] if i.num_clbits > 0 else []) builder = CircuitBuilder(qregs, cregs) builder.add_qiskit_data(i.definition) subc = builder.circuit() if optype == OpType.CircBox: cbox = CircBox(subc) self.tkc.add_circbox(cbox, qubits + bits, **condition_kwargs) else: # warning, this will catch all `Gate` instances # that were not picked up as a subclass in _known_qiskit_gate params = [param_to_tk(p) for p in i.params] gate_def = CustomGateDef.define(i.name, subc, list(subc.free_symbols())) self.tkc.add_custom_gate(gate_def, params, qubits + bits) else: params = [param_to_tk(p) for p in i.params] self.tkc.add_gate(optype, params, qubits + bits, **condition_kwargs)
def tk_to_cirq(tkcirc: Circuit, copy_all_qubits: bool = False) -> cirq.circuits.Circuit: """Converts a tket :py:class:`Circuit` object to a Cirq :py:class:`Circuit`. :param tkcirc: The input tket :py:class:`Circuit` :return: The Cirq :py:class:`Circuit` corresponding to the input circuit """ if copy_all_qubits: tkcirc = tkcirc.copy() for q in tkcirc.qubits: tkcirc.add_gate(OpType.noop, [q]) qmap = {} line_name = None grid_name = None # Since Cirq can only support registers of up to 2 dimensions, we explicitly # check for 3-dimensional registers whose third dimension is trivial. # SquareGrid architectures are of this form. indices = [qb.index for qb in tkcirc.qubits] is_flat_3d = all(idx[2] == 0 for idx in indices if len(idx) == 3) for qb in tkcirc.qubits: if len(qb.index) == 0: qmap.update({qb: cirq.ops.NamedQubit(qb.reg_name)}) elif len(qb.index) == 1: if line_name != None and line_name != qb.reg_name: raise NotImplementedError( "Cirq can only support a single linear register") line_name = qb.reg_name qmap.update({qb: LineQubit(qb.index[0])}) elif len(qb.index) == 2 or (len(qb.index) == 3 and is_flat_3d): if grid_name != None and grid_name != qb.reg_name: raise NotImplementedError( "Cirq can only support a single grid register") grid_name = qb.reg_name qmap.update({qb: GridQubit(qb.index[0], qb.index[1])}) else: raise NotImplementedError( "Cirq can only support registers of dimension <=2") oplst = [] for command in tkcirc: op = command.op optype = op.type try: gatetype = _ops2cirq_mapping[optype] except KeyError as error: raise NotImplementedError("Cannot convert tket Op to Cirq gate: " + op.get_name()) from error if optype == OpType.Measure: qid = qmap[command.args[0]] bit = command.args[1] cirqop = cirq.ops.measure(qid, key=bit.__repr__()) else: qids = [qmap[qbit] for qbit in command.args] params = op.params if len(params) == 0: cirqop = gatetype(*qids) elif optype == OpType.PhasedX: cirqop = gatetype(phase_exponent=params[1], exponent=params[0])(*qids) elif optype == OpType.FSim: cirqop = gatetype(theta=float(params[0] * pi), phi=float(params[1] * pi))(*qids) elif optype == OpType.PhasedISWAP: cirqop = gatetype(phase_exponent=params[0], exponent=params[1])(*qids) else: cirqop = gatetype(exponent=params[0])(*qids) oplst.append(cirqop) try: coeff = cmath.exp(float(tkcirc.phase) * cmath.pi * 1j) if coeff != 1.0: oplst.append(cirq.ops.GlobalPhaseOperation(coeff)) except ValueError: warning( "Global phase is dependent on a symbolic parameter, so cannot adjust for " "phase") return cirq.circuits.Circuit(*oplst)
def test_honeywell() -> None: token = os.getenv("HQS_AUTH") backend = HoneywellBackend(device_name="HQS-LT-1.0-APIVAL", machine_debug=skip_remote_tests) c = Circuit(4, 4, "test 1") c.H(0) c.CX(0, 1) c.Rz(0.3, 2) c.CSWAP(0, 1, 2) c.CRz(0.4, 2, 3) c.CY(1, 3) c.ZZPhase(0.1, 2, 0) c.Tdg(3) c.measure_all() backend.compile_circuit(c) n_shots = 4 handle = backend.process_circuits([c], n_shots)[0] correct_shots = np.zeros((4, 4)) correct_counts = {(0, 0, 0, 0): 4} res = backend.get_result(handle, timeout=49) shots = res.get_shots() counts = res.get_counts() assert backend.circuit_status(handle).status is StatusEnum.COMPLETED assert np.all(shots == correct_shots) assert counts == correct_counts newshots = backend.get_shots(c, 4, timeout=49) assert np.all(newshots == correct_shots) newcounts = backend.get_counts(c, 4) assert newcounts == correct_counts if token is None: assert backend.device is None
def test_classical() -> None: # circuit to cover capabilities covered in HQS example notebook c = Circuit(1) a = c.add_c_register("a", 8) b = c.add_c_register("b", 10) c.add_c_register("c", 10) c.add_c_setbits([True], [a[0]]) c.add_c_setbits([False, True] + [False] * 6, list(a)) c.add_c_setbits([True, True] + [False] * 8, list(b)) c.X(0, condition=reg_eq(a ^ b, 1)) c.X(0, condition=(a[0] ^ b[0])) c.X(0, condition=reg_eq(a & b, 1)) c.X(0, condition=reg_eq(a | b, 1)) c.X(0, condition=a[0]) c.X(0, condition=reg_neq(a, 1)) c.X(0, condition=if_not_bit(a[0])) c.X(0, condition=reg_gt(a, 1)) c.X(0, condition=reg_lt(a, 1)) c.X(0, condition=reg_geq(a, 1)) c.X(0, condition=reg_leq(a, 1)) b = HoneywellBackend("HQS-LT-S1-APIVAL") b.compile_circuit(c) assert b.get_counts(c, 10)
def circuits( draw: Callable[[SearchStrategy[Any]], Any], n_qubits: SearchStrategy[int] = st.integers(min_value=2, max_value=6), depth: SearchStrategy[int] = st.integers(min_value=1, max_value=100), ) -> Circuit: total_qubits = draw(n_qubits) circuit = Circuit(total_qubits, total_qubits) for _ in range(draw(depth)): gate = draw(st.sampled_from(list(_GATE_SET))) control = draw(st.integers(min_value=0, max_value=total_qubits - 1)) if gate == OpType.ZZMax: target = draw( st.integers(min_value=0, max_value=total_qubits - 1).filter(lambda x: x != control)) circuit.add_gate(gate, [control, target]) elif gate == OpType.Measure: circuit.add_gate(gate, [control, control]) circuit.add_gate(OpType.Reset, [control]) elif gate == OpType.Rz: param = draw(st.floats(min_value=0, max_value=2)) circuit.add_gate(gate, [param], [control]) elif gate == OpType.PhasedX: param1 = draw(st.floats(min_value=0, max_value=2)) param2 = draw(st.floats(min_value=0, max_value=2)) circuit.add_gate(gate, [param1, param2], [control]) circuit.measure_all() return circuit
def test_aqt() -> None: # Run a circuit on the noisy simulator. token = cast(str, os.getenv("AQT_AUTH")) b = AQTBackend(device_name="sim/noise-model-1", access_token=token, label="test 1") c = Circuit(4, 4) c.H(0) c.CX(0, 1) c.Rz(0.3, 2) c.CSWAP(0, 1, 2) c.CRz(0.4, 2, 3) c.CY(1, 3) c.add_barrier([0, 1]) c.ZZPhase(0.1, 2, 0) c.Tdg(3) c.measure_all() b.compile_circuit(c) n_shots = 10 shots = b.get_shots(c, n_shots, seed=1, timeout=30) counts = b.get_counts(c, n_shots) assert len(shots) == n_shots assert sum(counts.values()) == n_shots
# # Circuit analysis: tket example # This notebook will introduce the basic methods of analysis and visualization of circuits available in `pytket`. # # It makes use of the modules `pytket_qiskit` and `pytket_cirq` for visualization; these need to be installed (with `pip`) in addition to `pytket`. # # We'll start by generating a small circuit to use as an example, and give it a name. from pytket.circuit import Circuit, OpType c = Circuit(4, name="example") c.add_gate(OpType.CU1, 0.5, [0, 1]) c.H(0).X(1).Y(2).Z(3) c.X(0).CX(1, 2).Y(1).Z(2).H(3) c.Y(0).Z(1) c.add_gate(OpType.CU1, 0.5, [2, 3]) c.H(2).X(3) c.Z(0).H(1).X(2).Y(3).CX(3, 0) # ## Basic statistics # From the circuit we can easily read off the number of qubits ... c.n_qubits # ... the name ... c.name # ... the overall depth of the circuit ...
def cirq_to_tk(circuit: cirq.circuits.Circuit) -> Circuit: """Converts a Cirq :py:class:`Circuit` to a tket :py:class:`Circuit` object. :param circuit: The input Cirq :py:class:`Circuit` :raises NotImplementedError: If the input contains a Cirq :py:class:`Circuit` operation which is not yet supported by pytket :return: The tket :py:class:`Circuit` corresponding to the input circuit """ tkcirc = Circuit() qmap = {} for qb in circuit.all_qubits(): if isinstance(qb, LineQubit): uid = Qubit("q", qb.x) elif isinstance(qb, GridQubit): uid = Qubit("g", qb.row, qb.col) elif isinstance(qb, cirq.ops.NamedQubit): uid = Qubit(qb.name) else: raise NotImplementedError("Cannot convert qubits of type " + str(type(qb))) tkcirc.add_qubit(uid) qmap.update({qb: uid}) for moment in circuit: for op in moment.operations: if isinstance(op, cirq.ops.GlobalPhaseOperation): tkcirc.add_phase(cmath.phase(op.coefficient) / pi) continue gate = op.gate gatetype = type(gate) qb_lst = [qmap[q] for q in op.qubits] if isinstance(gate, cirq_common.HPowGate) and gate.exponent == 1: gate = cirq_common.H elif (gatetype == cirq_common.CNotPowGate and cast(cirq_common.CNotPowGate, gate).exponent == 1): gate = cirq_common.CNOT elif (gatetype == cirq_pauli._PauliX and cast(cirq_pauli._PauliX, gate).exponent == 1): gate = cirq_pauli.X elif (gatetype == cirq_pauli._PauliY and cast(cirq_pauli._PauliY, gate).exponent == 1): gate = cirq_pauli.Y elif (gatetype == cirq_pauli._PauliZ and cast(cirq_pauli._PauliZ, gate).exponent == 1): gate = cirq_pauli.Z if gate in _constant_gates: try: optype = _cirq2ops_mapping[gate] except KeyError as error: raise NotImplementedError( "Operation not supported by tket: " + str(op.gate)) from error params = [] elif isinstance(gate, cirq_common.MeasurementGate): uid = Bit(gate.key) tkcirc.add_bit(uid) tkcirc.Measure(*qb_lst, uid) continue elif isinstance(gate, cirq.ops.PhasedXPowGate): optype = OpType.PhasedX pe = gate.phase_exponent params = [gate.exponent, pe] elif isinstance(gate, cirq.ops.FSimGate): optype = OpType.FSim params = [gate.theta / pi, gate.phi / pi] elif isinstance(gate, cirq.ops.PhasedISwapPowGate): optype = OpType.PhasedISWAP params = [gate.phase_exponent, gate.exponent] else: try: optype = _cirq2ops_mapping[gatetype] params = [cast(Any, gate).exponent] except (KeyError, AttributeError) as error: raise NotImplementedError( "Operation not supported by tket: " + str(op.gate)) from error tkcirc.add_gate(optype, params, qb_lst) return tkcirc
def test_statevector() -> None: b = AerStateBackend() circ = Circuit(3, name="test") circ.H(2) circ.X(0) circ.H(0) circ.CX(0, 1) circ.CZ(1, 2) circ.Sdg(0) circ.Tdg(1) circ.Z(1) circ.T(2) circ.Rx(0.3333, 1) circ.Rz(0.3333, 1) zxcirc = tk_to_pyzx(circ) assert zxcirc.name == circ.name b.compile_circuit(circ) state = b.get_state(circ) circ2 = pyzx_to_tk(zxcirc) assert circ2.name == circ.name b.compile_circuit(circ2) state2 = b.get_state(circ2) assert np.allclose(state, state2, atol=1e-10)
def _from_tk1(a: float, b: float, c: float) -> Circuit: circ = Circuit(1) circ.Rz(c, 0) circ.Rx(b, 0) circ.Rz(a, 0) return circ
def test_invalid_gate() -> None: circ = Circuit(1, name="test") circ.measure_all() with pytest.raises(Exception) as excinfo: _ = tk_to_pyzx(circ) assert "as the gate type is unrecognised." in str(excinfo.value)
# We will use Qiskit for circuit visualisation and for an example backend. For this it is necessary to have installed `pytket_qiskit` via `pip`. # # ## Passes # The basic mechanism of compilation is the 'pass', which is a transform that can be applied to a circuit. There is an extensive library of passes in `pytket`, and several standard ways in which they can be combined to form new passes. For example: from pytket.passes import DecomposeMultiQubitsIBM pass1 = DecomposeMultiQubitsIBM() # This pass converts all multi-qubit gates into CX and single-qubit gates. So let's create a circuit containing some non-CX multi-qubit gates: from pytket.circuit import Circuit circ = Circuit(3) circ.CRz(0.5, 0, 1) circ.T(2) circ.CSWAP(2, 0, 1) # In order to apply a pass to a circuit, we must first create a `CompilationUnit` from it. We can think of this as a 'bridge' between the circuit and the pass. The `CompilationUnit` is constructed from the circuit; the pass is applied to the `CompilationUnit`; and the transformed circuit is extracted from the `CompilationUnit`: from pytket.predicates import CompilationUnit cu = CompilationUnit(circ) pass1.apply(cu) circ1 = cu.circuit # Let's have a look at the result of the transformation: print(circ1.get_commands())
for filename in os.listdir(op_directory): path = op_directory + "/" + filename with open(path, "rb") as pickle_in: qubit_pauli_operator = pickle.load(pickle_in) name = filename.replace(".pickle", "") print(name) active_spin_orbitals = orbitals_lookup_table[name] # Qiskit removed 2 qubits per circuit for us using Z2 # Symmetries for the Parity encoding if encoding_name == "P": n_qubits = active_spin_orbitals - 2 else: n_qubits = active_spin_orbitals initial_circ = Circuit(n_qubits) print("sequencing") t1_a = datetime.datetime.now() set_synth_circuit = gen_term_sequence_circuit(qubit_pauli_operator, initial_circ) t1_b = datetime.datetime.now() print("Partitions: {}".format( set_synth_circuit.n_gates_of_type(OpType.CircBox))) naive_circuit = set_synth_circuit.copy() pairwise_circuit = set_synth_circuit.copy() Transform.DecomposeBoxes().apply(naive_circuit) # Naive construction: decompose each Pauli exponential invidually naive_cx_count = naive_circuit.n_gates_of_type(OpType.CX)