def test_expw_matrix(half_turns): if (version[0] == 0 and version[1] <= 3): nptest.assert_array_almost_equal(xmon_gates.Exp11Gate(half_turns=half_turns).matrix, google.Exp11Gate(half_turns=half_turns).matrix()) else: nptest.assert_array_almost_equal(xmon_gates.Exp11Gate(half_turns=half_turns).matrix, unitary(ops.CZPowGate(exponent=half_turns)))
def fsim_gate(a, b, theta, phi): """FSimGate has a default decomposition in cirq to XXPowGate and YYPowGate, which is an awkward decomposition for this gate set. Decompose into ISWAP and CZ instead.""" if theta != 0.0: yield ops.ISWAP(a, b)**(-2 * theta / np.pi) if phi != 0.0: yield ops.CZPowGate(exponent=-phi / np.pi)(a, b)
def _exp11Gate(cmd, mapping, qubits): """ Translate a ExpW gate into a Cirq gate. Args: - cmd (:class:`projectq.ops.Command`) - a projectq command instance - mapping (:class:`dict`) - a dictionary of qubit mappings - qubits (list of :class:cirq.QubitID`) - cirq qubits Returns: - :class:`cirq.Operation` """ qb_pos = [mapping[qb.id] for qr in cmd.qubits for qb in qr] assert len(qb_pos) == 2 cirqGate = cop.CZPowGate(exponent=cmd.gate.angle / cmath.pi) return cirqGate(*[qubits[idx] for idx in qb_pos])
# See the License for the specific language governing permissions and # limitations under the License. from typing import List, Union, Sequence, Dict, Optional import numpy as np from cirq import ops from cirq.circuits import Circuit DEFAULT_GATE_DOMAIN: Dict[ops.Gate, int] = { ops.CNOT: 2, ops.CZ: 2, ops.H: 1, ops.ISWAP: 2, ops.CZPowGate(): 2, ops.S: 1, ops.SWAP: 2, ops.T: 1, ops.X: 1, ops.Y: 1, ops.Z: 1 } def random_circuit( qubits: Union[Sequence[ops.Qid], int], n_moments: int, op_density: float, gate_domain: Optional[Dict[ops.Gate, int]] = None, random_state: Optional[Union[np.random.RandomState, int]] = None
def random_rotations_between_grid_interaction_layers_circuit( qubits: Iterable['cirq.GridQubit'], depth: int, *, # forces keyword arguments two_qubit_op_factory: Callable[ ['cirq.GridQubit', 'cirq.GridQubit', 'np.random.RandomState'], 'cirq.OP_TREE'] = lambda a, b, _: ops.CZPowGate()(a, b), pattern: Sequence[GridInteractionLayer] = GRID_STAGGERED_PATTERN, single_qubit_gates: Sequence['cirq.Gate'] = ( ops.X**0.5, ops.Y**0.5, ops.PhasedXPowGate(phase_exponent=0.25, exponent=0.5), ), add_final_single_qubit_layer: bool = True, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, ) -> 'cirq.Circuit': """Generate a random quantum circuit of a particular form. This construction is based on the circuits used in the paper https://www.nature.com/articles/s41586-019-1666-5. The generated circuit consists of a number of "cycles", this number being specified by `depth`. Each cycle is actually composed of two sub-layers: a layer of single-qubit gates followed by a layer of two-qubit gates, controlled by their respective arguments, see below. The pairs of qubits in a given entangling layer is controlled by the `pattern` argument, see below. Args: qubits: The qubits to use. depth: The number of cycles. two_qubit_op_factory: A callable that returns a two-qubit operation. These operations will be generated with calls of the form `two_qubit_op_factory(q0, q1, prng)`, where `prng` is the pseudorandom number generator. pattern: A sequence of GridInteractionLayers, each of which determine which pairs of qubits are entangled. The layers in a pattern are iterated through sequentially, repeating until `depth` is reached. single_qubit_gates: Single-qubit gates are selected randomly from this sequence. No qubit is acted upon by the same single-qubit gate in consecutive cycles. If only one choice of single-qubit gate is given, then this constraint is not enforced. add_final_single_qubit_layer: Whether to include a final layer of single-qubit gates after the last cycle. seed: A seed or random state to use for the pseudorandom number generator. """ prng = value.parse_random_state(seed) qubits = list(qubits) coupled_qubit_pairs = _coupled_qubit_pairs(qubits) circuit = circuits.Circuit() previous_single_qubit_layer = circuits.Moment() single_qubit_layer_factory = _single_qubit_gates_arg_to_factory( single_qubit_gates=single_qubit_gates, qubits=qubits, prng=prng) for i in range(depth): single_qubit_layer = single_qubit_layer_factory.new_layer( previous_single_qubit_layer) circuit += single_qubit_layer two_qubit_layer = _two_qubit_layer(coupled_qubit_pairs, two_qubit_op_factory, pattern[i % len(pattern)], prng) circuit += two_qubit_layer previous_single_qubit_layer = single_qubit_layer if add_final_single_qubit_layer: circuit += single_qubit_layer_factory.new_layer( previous_single_qubit_layer) return circuit
def random_rotations_between_two_qubit_circuit( q0: 'cirq.Qid', q1: 'cirq.Qid', depth: int, two_qubit_op_factory: Callable[ ['cirq.Qid', 'cirq.Qid', 'np.random.RandomState'], 'cirq.OP_TREE'] = lambda a, b, _: ops.CZPowGate()(a, b), single_qubit_gates: Sequence['cirq.Gate'] = ( ops.X**0.5, ops.Y**0.5, ops.PhasedXPowGate(phase_exponent=0.25, exponent=0.5), ), add_final_single_qubit_layer: bool = True, seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, ) -> 'cirq.Circuit': """Generate a random two-qubit quantum circuit. This construction uses a similar structure to those in the paper https://www.nature.com/articles/s41586-019-1666-5. The generated circuit consists of a number of "cycles", this number being specified by `depth`. Each cycle is actually composed of two sub-layers: a layer of single-qubit gates followed by a layer of two-qubit gates, controlled by their respective arguments, see below. Args: q0: The first qubit q1: The second qubit depth: The number of cycles. two_qubit_op_factory: A callable that returns a two-qubit operation. These operations will be generated with calls of the form `two_qubit_op_factory(q0, q1, prng)`, where `prng` is the pseudorandom number generator. single_qubit_gates: Single-qubit gates are selected randomly from this sequence. No qubit is acted upon by the same single-qubit gate in consecutive cycles. If only one choice of single-qubit gate is given, then this constraint is not enforced. add_final_single_qubit_layer: Whether to include a final layer of single-qubit gates after the last cycle (subject to the same non-consecutivity constraint). seed: A seed or random state to use for the pseudorandom number generator. """ prng = value.parse_random_state(seed) circuit = circuits.Circuit() previous_single_qubit_layer = circuits.Moment() single_qubit_layer_factory = _single_qubit_gates_arg_to_factory( single_qubit_gates=single_qubit_gates, qubits=(q0, q1), prng=prng) for _ in range(depth): single_qubit_layer = single_qubit_layer_factory.new_layer( previous_single_qubit_layer) circuit += single_qubit_layer circuit += two_qubit_op_factory(q0, q1, prng) previous_single_qubit_layer = single_qubit_layer if add_final_single_qubit_layer: circuit += single_qubit_layer_factory.new_layer( previous_single_qubit_layer) return circuit
protocols.unitary(test_circuit), protocols.unitary(cirq_circuit), atol=1e-7, ) # Cirq AAPowGate has a different global phase than braket AA which gets # lost in translation. Here, AA = XX, YY, or ZZ. if not isinstance(common_gate, (ops.XXPowGate, ops.YYPowGate, ops.ZZPowGate)): assert _equal(test_circuit, cirq_circuit, require_qubit_equality=True) @pytest.mark.parametrize( "uncommon_gate", [ops.CNotPowGate(exponent=-1 / 17), ops.CZPowGate(exponent=2 / 7)], ) def test_to_from_braket_uncommon_two_qubit_gates(uncommon_gate): """These gates get decomposed when converting Cirq -> Braket -> Cirq, but the unitaries should be equal up to global phase. """ cirq_circuit = Circuit(uncommon_gate.on(*LineQubit.range(2))) test_circuit = from_braket(to_braket(cirq_circuit)) testing.assert_allclose_up_to_global_phase( protocols.unitary(test_circuit), protocols.unitary(cirq_circuit), atol=1e-7, )
protocols.unitary(test_circuit), protocols.unitary(cirq_circuit), atol=1e-7, ) # Cirq AAPowGate has a different global phase than braket AA which gets # lost in translation. Here, AA = XX, YY, or ZZ. if not isinstance( common_gate, (ops.XXPowGate, ops.YYPowGate, ops.ZZPowGate) ): assert _equal(test_circuit, cirq_circuit, require_qubit_equality=True) @pytest.mark.parametrize( "uncommon_gate", [ops.CNotPowGate(exponent=-1 / 17), ops.CZPowGate(exponent=2 / 7)], ) def test_to_from_braket_uncommon_two_qubit_gates(uncommon_gate): """These gates get decomposed when converting Cirq -> Braket -> Cirq, but the unitaries should be equal up to global phase. """ cirq_circuit = Circuit(uncommon_gate.on(*LineQubit.range(2))) test_circuit = from_braket(to_braket(cirq_circuit)) testing.assert_allclose_up_to_global_phase( protocols.unitary(test_circuit), protocols.unitary(cirq_circuit), atol=1e-7, )