def test_teleportation_diagram(): ali = ops.NamedQubit('alice') car = ops.NamedQubit('carrier') bob = ops.NamedQubit('bob') circuit = Circuit.from_ops( ops.H(car), ops.CNOT(car, bob), ops.X(ali)**0.5, ops.CNOT(ali, car), ops.H(ali), [ops.measure(ali), ops.measure(car)], ops.CNOT(car, bob), ops.CZ(ali, bob)) diagram = circuit_to_latex_using_qcircuit( circuit, qubit_order=ops.QubitOrder.explicit([ali, car, bob])) assert diagram.strip() == """ \\Qcircuit @R=1em @C=0.75em { \\\\ \\lstick{\\text{alice}}& \\qw &\\qw & \\gate{\\text{X}^{0.5}} \\qw & \\control \\qw & \\gate{\\text{H}} \\qw & \\meter \\qw &\\qw & \\control \\qw &\\qw\\\\ \\lstick{\\text{carrier}}& \\qw & \\gate{\\text{H}} \\qw & \\control \\qw & \\targ \\qw \\qwx &\\qw & \\meter \\qw & \\control \\qw &\\qw \\qwx &\\qw\\\\ \\lstick{\\text{bob}}& \\qw &\\qw & \\targ \\qw \\qwx &\\qw &\\qw &\\qw & \\targ \\qw \\qwx & \\control \\qw \\qwx &\\qw \\\\ \\\\ } """.strip()
def test_inverse_of_invertible_op_tree(): def rev_freeze(root): return ops.freeze_op_tree(ops.inverse_of_invertible_op_tree(root)) operations = [ ops.Operation(_FlipGate(i), [ops.NamedQubit(str(i))]) for i in range(10) ] expected = [ ops.Operation(_FlipGate(~i), [ops.NamedQubit(str(i))]) for i in range(10) ] # Just an item. assert rev_freeze(operations[0]) == expected[0] # Flat list. assert rev_freeze(operations) == tuple(expected[::-1]) # Tree. assert (rev_freeze( (operations[1:5], operations[0], operations[5:])) == (tuple(expected[5:][::-1]), expected[0], tuple(expected[1:5][::-1]))) # Flattening after reversing is equivalent to reversing then flattening. t = (operations[1:5], operations[0], operations[5:]) assert (tuple(ops.flatten_op_tree(rev_freeze(t))) == tuple( rev_freeze(ops.flatten_op_tree(t))))
def test_init(): r = ScheduledOperation(time=Timestamp(picos=5), duration=Duration(picos=7), operation=ops.Operation(ops.H, [ops.NamedQubit('a')])) assert r.time == Timestamp(picos=5) assert r.duration == Duration(picos=7) assert r.operation == ops.Operation(ops.H, [ops.NamedQubit('a')])
def test_text_diagrams(): a = ops.NamedQubit('a') b = ops.NamedQubit('b') circuit = Circuit.from_ops(ops.SWAP(a, b), ops.X(a), ops.Y(a), ops.Z(a), ops.CZ(a, b), ops.CNOT(a, b), ops.CNOT(b, a), ops.H(a)) assert circuit.to_text_diagram().strip() == """ a: ───×───X───Y───Z───@───@───X───H─── │ │ │ │ b: ───×───────────────@───X───@─────── """.strip()
def test_measure_each(): a = ops.NamedQubit('a') b = ops.NamedQubit('b') assert cirq.measure_each() == [] assert cirq.measure_each(a) == [cirq.measure(a)] assert cirq.measure_each(a, b) == [cirq.measure(a), cirq.measure(b)] assert cirq.measure_each(a, b, key_func=lambda e: e.name + '!') == [ cirq.measure(a, key='a!'), cirq.measure(b, key='b!') ]
def test_measurement_qubit_count_vs_mask_length(): a = ops.NamedQubit('a') b = ops.NamedQubit('b') c = ops.NamedQubit('c') _ = cirq.MeasurementGate(invert_mask=(True, )).on(a) _ = cirq.MeasurementGate(invert_mask=(True, False)).on(a, b) _ = cirq.MeasurementGate(invert_mask=(True, False, True)).on(a, b, c) with pytest.raises(ValueError): _ = cirq.MeasurementGate(invert_mask=(True, False)).on(a) with pytest.raises(ValueError): _ = cirq.MeasurementGate(invert_mask=(True, False, True)).on(a, b)
def test_measure(): a = ops.NamedQubit('a') b = ops.NamedQubit('b') # Empty application. with pytest.raises(ValueError): _ = cirq.measure() assert cirq.measure(a) == cirq.MeasurementGate(key='a').on(a) assert cirq.measure(a, b) == cirq.MeasurementGate(key='a,b').on(a, b) assert cirq.measure(b, a) == cirq.MeasurementGate(key='b,a').on(b, a) assert cirq.measure(a, key='b') == cirq.MeasurementGate(key='b').on(a) assert cirq.measure(a, invert_mask=(True, )) == cirq.MeasurementGate( key='a', invert_mask=(True, )).on(a)
def test_interchangeable_qubit_eq(): a = ops.NamedQubit('a') b = ops.NamedQubit('b') c = ops.NamedQubit('c') eq = EqualsTester() eq.add_equality_group(ops.SWAP(a, b), ops.SWAP(b, a)) eq.add_equality_group(ops.SWAP(a, c)) eq.add_equality_group(ops.CZ(a, b), ops.CZ(b, a)) eq.add_equality_group(ops.CZ(a, c)) eq.add_equality_group(ops.CNOT(a, b)) eq.add_equality_group(ops.CNOT(b, a)) eq.add_equality_group(ops.CNOT(a, c))
def random_circuit( qubits: Union[Sequence[ops.Qid], int], n_moments: int, op_density: float, gate_domain: Optional[Dict[ops.Gate, int]] = None) -> Circuit: """Generates a random circuit. Args: qubits: the qubits that the circuit acts on. Because the qubits on which an operation acts are chosen randomly, not all given qubits may be acted upon. n_moments: the number of moments in the generated circuit. op_density: the expected proportion of qubits that are acted on in any moment. gate_domain: The set of gates to choose from, with a specified arity. Raises: ValueError: * op_density is not in (0, 1). * gate_domain is empty. * qubits is an int less than 1 or an empty sequence. Returns: The randomly generated Circuit. """ if not 0 < op_density < 1: raise ValueError('op_density must be in (0, 1).') if gate_domain is None: gate_domain = DEFAULT_GATE_DOMAIN if not gate_domain: raise ValueError('gate_domain must be non-empty') max_arity = max(gate_domain.values()) if isinstance(qubits, int): qubits = tuple(ops.NamedQubit(str(i)) for i in range(qubits)) n_qubits = len(qubits) if n_qubits < 1: raise ValueError('At least one qubit must be specified.') moments: List[ops.Moment] = [] for _ in range(n_moments): operations = [] free_qubits = set(q for q in qubits) while len(free_qubits) >= max_arity: gate, arity = choice(tuple(gate_domain.items())) op_qubits = sample(free_qubits, arity) free_qubits.difference_update(op_qubits) if random() <= op_density: operations.append(gate(*op_qubits)) moments.append(ops.Moment(operations)) return Circuit(moments)
def test_works_with_basic_gates(): a = ops.NamedQubit('a') b = ops.NamedQubit('b') basics = [ ops.X(a), ops.Y(a)**0.5, ops.Z(a), ops.CZ(a, b)**-0.25, ops.CNOT(a, b), ops.H(b), ops.SWAP(a, b) ] assert list(ops.inverse_of_invertible_op_tree(basics)) == [ ops.SWAP(a, b), ops.H(b), ops.CNOT(a, b), ops.CZ(a, b)**0.25, ops.Z(a), ops.Y(a)**-0.5, ops.X(a), ]
def random_two_qubit_circuit_with_czs( num_czs: int = 3, q0: Qid = None, q1: Qid = None, random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, ) -> circuits.Circuit: """Creates a random two qubit circuit with the given number of CNOTs. The resulting circuit will have `num_cnots` number of CNOTs that will be surrounded by random `PhasedXPowGate` instances on both qubits. Args: num_czs: the number of CNOTs to be guaranteed in the circuit q0: the first qubit the circuit should operate on q1: the second qubit the circuit should operate on random_state: an optional random seed Returns: the random two qubit circuit """ prng = value.parse_random_state(random_state) q0 = ops.NamedQubit('q0') if q0 is None else q0 q1 = ops.NamedQubit('q1') if q1 is None else q1 def random_one_qubit_gate(): return ops.PhasedXPowGate(phase_exponent=prng.rand(), exponent=prng.rand()) def one_cz(): return [ ops.CZ.on(q0, q1), random_one_qubit_gate().on(q0), random_one_qubit_gate().on(q1), ] return circuits.Circuit([ random_one_qubit_gate().on(q0), random_one_qubit_gate().on(q1), [one_cz() for _ in range(num_czs)], ])
def named_qubit_from_proto_id(proto_id: str) -> 'cirq.NamedQubit': """Parse a proto id to a `cirq.NamedQubit' This simply returns a `cirq.NamedQubit` with a name equal to `proto_id`. """ return ops.NamedQubit(proto_id)
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 ) -> Circuit: """Generates a random circuit. Args: qubits: If a sequence of qubits, then these are the qubits that the circuit should act on. Because the qubits on which an operation acts are chosen randomly, not all given qubits may be acted upon. If an int, then this number of qubits will be automatically generated. n_moments: the number of moments in the generated circuit. op_density: the expected proportion of qubits that are acted on in any moment. gate_domain: The set of gates to choose from, with a specified arity. random_state: Random state or random state seed. Raises: ValueError: * op_density is not in (0, 1). * gate_domain is empty. * qubits is an int less than 1 or an empty sequence. Returns: The randomly generated Circuit. """ if not 0 < op_density < 1: raise ValueError('op_density must be in (0, 1).') if gate_domain is None: gate_domain = DEFAULT_GATE_DOMAIN if not gate_domain: raise ValueError('gate_domain must be non-empty') max_arity = max(gate_domain.values()) if isinstance(qubits, int): qubits = tuple(ops.NamedQubit(str(i)) for i in range(qubits)) n_qubits = len(qubits) if n_qubits < 1: raise ValueError('At least one qubit must be specified.') if random_state is None: prng = np.random elif isinstance(random_state, np.random.RandomState): prng = random_state else: prng = np.random.RandomState(random_state) moments: List[ops.Moment] = [] gate_arity_pairs = tuple(gate_domain.items()) num_gates = len(gate_domain) for _ in range(n_moments): operations = [] free_qubits = set(qubits) while len(free_qubits) >= max_arity: gate, arity = gate_arity_pairs[prng.randint(num_gates)] op_qubits = prng.choice(list(free_qubits), size=arity, replace=False) free_qubits.difference_update(op_qubits) if prng.rand() <= op_density: operations.append(gate(*op_qubits)) moments.append(ops.Moment(operations)) return Circuit(moments)
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: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None, ) -> circuits.Circuit: """Generates a random circuit. Args: qubits: If a sequence of qubits, then these are the qubits that the circuit should act on. Because the qubits on which an operation acts are chosen randomly, not all given qubits may be acted upon. If an int, then this number of qubits will be automatically generated, and the qubits will be `cirq.NamedQubits` with names given by the integers in `range(qubits)`. n_moments: The number of moments in the generated circuit. op_density: The probability that a gate is selected to operate on randomly selected qubits. Note that this is not the expected number of qubits that are acted on, since there are cases where the number of qubits that a gate acts on does not evenly divide the total number of qubits. gate_domain: The set of gates to choose from, specified as a dictionary where each key is a gate and the value of the key is the number of qubits the gate acts on. If not provided, the default gate domain is {X, Y, Z, H, S, T, CNOT, CZ, SWAP, ISWAP, CZPowGate()}. Only gates which act on a number of qubits less than len(qubits) (or qubits if provided as an int) are selected from the gate domain. random_state: Random state or random state seed. Raises: ValueError: * op_density is not in (0, 1]. * gate_domain is empty. * qubits is an int less than 1 or an empty sequence. Returns: The randomly generated Circuit. """ if not 0 < op_density <= 1: raise ValueError(f'op_density must be in (0, 1] but was {op_density}.') if gate_domain is None: gate_domain = DEFAULT_GATE_DOMAIN if not gate_domain: raise ValueError('gate_domain must be non-empty.') if isinstance(qubits, int): qubits = tuple(ops.NamedQubit(str(i)) for i in range(qubits)) n_qubits = len(qubits) if n_qubits < 1: raise ValueError('At least one qubit must be specified.') gate_domain = {k: v for k, v in gate_domain.items() if v <= n_qubits} if not gate_domain: raise ValueError(f'After removing gates that act on less than ' f'{n_qubits} qubits, gate_domain had no gates.') max_arity = max(gate_domain.values()) prng = value.parse_random_state(random_state) moments: List[circuits.Moment] = [] gate_arity_pairs = sorted(gate_domain.items(), key=repr) num_gates = len(gate_domain) for _ in range(n_moments): operations = [] free_qubits = set(qubits) while len(free_qubits) >= max_arity: gate, arity = gate_arity_pairs[prng.randint(num_gates)] op_qubits = prng.choice(sorted(free_qubits), size=arity, replace=False) free_qubits.difference_update(op_qubits) if prng.rand() <= op_density: operations.append(gate(*op_qubits)) moments.append(circuits.Moment(operations)) return circuits.Circuit(moments)