def test_symbolic_c_rz(self): gate = CRz(sympy.Symbol("θ")) qubits = cirq.LineQubit.range(2) control, target = qubits circuit_decomposed = cirq.Circuit() circuit_decomposed.append( cirq.decompose(gate.on(control, target), keep=is_a_basic_operation)) # print("Decomposed circuit of Rz(θ): \n{}".format(circuit_decomposed)) self.assertEqual( str(circuit_decomposed), "0: ───────────────@────────────────@───\n" " │ │\n" "1: ───Rz(0.5*θ)───X───Rz(-0.5*θ)───X───")
def test_decomposition_with_parameterization(n): angles = sympy.symbols([f'x_{i}' for i in range(2**n)]) exponent = sympy.Symbol('e') diagonal_gate = cirq.DiagonalGate(angles) ** exponent parameterized_op = diagonal_gate(*cirq.LineQubit.range(n)) decomposed_circuit = cirq.Circuit(cirq.decompose(parameterized_op)) for exponent_value in [-0.5, 0.5, 1]: for i in range(len(_candidate_angles) - 2**n + 1): resolver = {exponent: exponent_value} resolver.update( {angles[j]: x_j for j, x_j in enumerate(_candidate_angles[i : i + 2**n])} ) resolved_op = cirq.resolve_parameters(parameterized_op, resolver) resolved_circuit = cirq.resolve_parameters(decomposed_circuit, resolver) np.testing.assert_allclose( cirq.unitary(resolved_op), cirq.unitary(resolved_circuit), atol=1e-8 )
def test_parameterize(resolve_fn, global_shift): parameterized_gate = cirq.PhasedXPowGate( exponent=sympy.Symbol('a'), phase_exponent=sympy.Symbol('b'), global_shift=global_shift ) assert cirq.pow(parameterized_gate, 5) == cirq.PhasedXPowGate( exponent=sympy.Symbol('a') * 5, phase_exponent=sympy.Symbol('b'), global_shift=global_shift ) assert cirq.unitary(parameterized_gate, default=None) is None assert cirq.is_parameterized(parameterized_gate) q = cirq.NamedQubit("q") parameterized_decomposed_circuit = cirq.Circuit(cirq.decompose(parameterized_gate(q))) for resolver in cirq.Linspace('a', 0, 2, 10) * cirq.Linspace('b', 0, 2, 10): resolved_gate = resolve_fn(parameterized_gate, resolver) assert resolved_gate == cirq.PhasedXPowGate( exponent=resolver.value_of('a'), phase_exponent=resolver.value_of('b'), global_shift=global_shift, ) np.testing.assert_allclose( cirq.unitary(resolved_gate(q)), cirq.unitary(resolve_fn(parameterized_decomposed_circuit, resolver)), atol=1e-8, ) unparameterized_gate = cirq.PhasedXPowGate( exponent=0.1, phase_exponent=0.2, global_shift=global_shift ) assert not cirq.is_parameterized(unparameterized_gate) assert cirq.is_parameterized(unparameterized_gate ** sympy.Symbol('a')) assert cirq.is_parameterized(unparameterized_gate ** (sympy.Symbol('a') + 1)) resolver = {'a': 0.5j} with pytest.raises(ValueError, match='complex value'): resolve_fn( cirq.PhasedXPowGate( exponent=sympy.Symbol('a'), phase_exponent=0.2, global_shift=global_shift ), resolver, ) with pytest.raises(ValueError, match='complex value'): resolve_fn( cirq.PhasedXPowGate( exponent=0.1, phase_exponent=sympy.Symbol('a'), global_shift=global_shift ), resolver, )
def test_arc_probs(input_prob_q0, input_prob_q1, expected_prob_q2, decompose): q0, q1, q2 = cirq.LineQubit.range(3) gate = ccb.BayesianNetworkGate( [('q0', input_prob_q0), ('q1', input_prob_q1), ('q2', None)], [('q2', ('q0', 'q1'), [0.1, 0.2, 0.3, 0.4])], ) if decompose: circuit = cirq.Circuit(cirq.decompose(gate.on(q0, q1, q2))) else: circuit = cirq.Circuit(gate.on(q0, q1, q2)) result = cirq.Simulator().simulate(circuit, qubit_order=[q0, q1, q2], initial_state=0) probs = [abs(x) ** 2 for x in result.state_vector(copy=True)] actual_prob_q2_is_one = sum(probs[1::2]) np.testing.assert_almost_equal(actual_prob_q2_is_one, expected_prob_q2, decimal=4)
def test_multi_clifford_decompose_by_unitary(): # Construct a random clifford gate: n, num_ops = 5, 20 # because we relied on unitary cannot test large-scale qubits gate_candidate = [cirq.X, cirq.Y, cirq.Z, cirq.H, cirq.S, cirq.CNOT, cirq.CZ] for _ in range(10): qubits = cirq.LineQubit.range(n) ops = [] for _ in range(num_ops): g = np.random.randint(len(gate_candidate)) indices = (np.random.randint(n),) if g < 5 else np.random.choice(n, 2, replace=False) ops.append(gate_candidate[g].on(*[qubits[i] for i in indices])) gate = cirq.CliffordGate.from_op_list(ops, qubits) decomposed_ops = cirq.decompose(gate.on(*qubits)) circ = cirq.Circuit(decomposed_ops) circ.append(cirq.I.on_each(qubits)) # make sure the dimension aligned. cirq.testing.assert_allclose_up_to_global_phase( cirq.unitary(gate), cirq.unitary(circ), atol=1e-7 )
def objective_function_monte_carlo_opt_env(self, params): self.u_params, self.v_params = (params[:self.n_state_params], params[self.n_state_params:]) U = self.state_ansatz(self.D, u_params) V = self.env_ansatz(self.D, v_params) qbs = cirq.LineQubit.range(int(2 * np.log2(self.D) + 2)) C = cirq.Circuit().from_ops(cirq.decompose(State(U, V, 2)(*qbs))) noise = cirq.ConstantQubitNoiseModel( cirq.depolarize(self.depolarizing_prob)) noisy_circuit = cirq.Circuit() for moment in C: noisy_circuit.append(noise.noisy_moment(moment, qbs)) return self.H.measure_energy(noisy_circuit, system_qubits, self.n_samples)
def act_gate_batch_on_qubits( gate_batch: GateBatch, qubits: typing.Iterable[cirq.Qid], decompose_in_elementary_ops: bool = True, as_circuits: bool = True ) -> typing.Union[GateOperationBatch, CircuitBatch]: """ Act a batch of gates on `qubits`. :param gate_batch: A batch of gates, whose shape is (batch_size, num_qubits). Any term in the batch contains `num_qubits` 1-qubit gates, which will be acted on each qubit in `qubits` in order. :param qubits: The qubits which the gates will act on. :param decompose_in_elementary_ops: Tells whether the gates in `gate_batch` should be decomposed into elementary operations. :param as_circuits: Tells whether the applied operations will be constructed as circuits. If False, the function will return a batch of series of operations; if True, the function will return a batch of circuits. :return: The result of `gate_batch` being acted on `qubits`. See `as_circuits` for more details. """ op_batch = [] for gate_series in gate_batch: op = [] for gate, q in zip(gate_series, qubits): if decompose_in_elementary_ops: op.append(cirq.decompose(gate(q))) else: op.append(gate(q)) if as_circuits: op_batch.append(cirq.Circuit(op)) else: op_batch.append(op) return op_batch
def test_scope_extern_mismatch(): q = cirq.LineQubit(0) inner = cirq.Circuit( cirq.measure(q, key='a'), cirq.X(q).with_classical_controls('b'), ) middle = cirq.Circuit( cirq.measure(q, key=cirq.MeasurementKey('b', ('0', ))), cirq.CircuitOperation(inner.freeze(), repetitions=2), ) outer_subcircuit = cirq.CircuitOperation(middle.freeze(), repetitions=2) circuit = outer_subcircuit.mapped_circuit(deep=True) internal_control_keys = [ str(condition) for op in circuit.all_operations() for condition in cirq.control_keys(op) ] assert internal_control_keys == ['b', 'b', 'b', 'b'] assert cirq.control_keys(outer_subcircuit) == {cirq.MeasurementKey('b')} assert cirq.control_keys(circuit) == {cirq.MeasurementKey('b')} cirq.testing.assert_has_diagram( cirq.Circuit(outer_subcircuit), """ [ [ 0: ───M('a')───X─── ] ] [ 0: ───M('0:b')───[ ║ ]──────────── ] 0: ───[ [ b: ════════════^═══ ](loops=2) ]──────────── [ ║ ] [ b: ══════════════╩══════════════════════════════════ ](loops=2) ║ b: ═══╩═══════════════════════════════════════════════════════════════════ """, use_unicode_characters=True, ) cirq.testing.assert_has_diagram( circuit, """ 0: ───M('0:0:b')───M('0:0:a')───X───M('0:1:a')───X───M('1:0:b')───M('1:0:a')───X───M('1:1:a')───X─── ║ ║ ║ ║ b: ═════════════════════════════^════════════════^═════════════════════════════^════════════════^═══ """, use_unicode_characters=True, ) assert circuit == cirq.Circuit(cirq.decompose(outer_subcircuit))
def test_tag_propagation(): # Tags are not propagated from the CircuitOperation to its components. # TODO: support tag propagation for better serialization. a, b, c = cirq.LineQubit.range(3) circuit = cirq.FrozenCircuit( cirq.X(a), cirq.H(b), cirq.H(c), cirq.CZ(a, c), ) op = cirq.CircuitOperation(circuit) test_tag = 'test_tag' op = op.with_tags(test_tag) assert test_tag in op.tags # TODO: Tags must propagate during decomposition. sub_ops = cirq.decompose(op) for op in sub_ops: assert test_tag not in op.tags
def multiply(self): circuit = cirq.Circuit() #for gate-counting purposes toffcount = 0 # step 1: toffolis for i in range(0, self.size): circuit.append( cirq.decompose(cirq.TOFFOLI(self.B[0], self.A[i], self.out[i]))) toffcount += 1 # step 2 (and 3): for i in range(1, self.size): circuit += ctrl_add(self.B[i], self.A, self.out[i:i + self.size + 2]).construct_circuit() print("Toffoli count in multiply: ") print(toffcount) return circuit
def test_scope_local(): q = cirq.LineQubit(0) inner = cirq.Circuit( cirq.measure(q, key='a'), cirq.X(q).with_classical_controls('a'), ) middle = cirq.Circuit(cirq.CircuitOperation(inner.freeze(), repetitions=2)) outer_subcircuit = cirq.CircuitOperation(middle.freeze(), repetitions=2) circuit = outer_subcircuit.mapped_circuit(deep=True) internal_control_keys = [ str(condition) for op in circuit.all_operations() for condition in cirq.control_keys(op) ] assert internal_control_keys == ['0:0:a', '0:1:a', '1:0:a', '1:1:a'] assert not cirq.control_keys(outer_subcircuit) assert not cirq.control_keys(circuit) cirq.testing.assert_has_diagram( cirq.Circuit(outer_subcircuit), """ [ [ 0: ───M───X─── ] ] 0: ───[ 0: ───[ ║ ║ ]──────────── ]──────────── [ [ a: ═══@═══^═══ ](loops=2) ](loops=2) """, use_unicode_characters=True, ) cirq.testing.assert_has_diagram( circuit, """ 0: ───────M───X───M───X───M───X───M───X─── ║ ║ ║ ║ ║ ║ ║ ║ 0:0:a: ═══@═══^═══╬═══╬═══╬═══╬═══╬═══╬═══ ║ ║ ║ ║ ║ ║ 0:1:a: ═══════════@═══^═══╬═══╬═══╬═══╬═══ ║ ║ ║ ║ 1:0:a: ═══════════════════@═══^═══╬═══╬═══ ║ ║ 1:1:a: ═══════════════════════════@═══^═══ """, use_unicode_characters=True, ) assert circuit == cirq.Circuit(cirq.decompose(outer_subcircuit))
def test_decompose_repeated_nested_measurements(): # Details of this test described at # https://tinyurl.com/measurement-repeated-circuitop#heading=h.sbgxcsyin9wt. a = cirq.LineQubit(0) op1 = (cirq.CircuitOperation(cirq.FrozenCircuit(cirq.measure( a, key='A'))).with_measurement_key_mapping({ 'A': 'B' }).repeat(2, ['zero', 'one'])) op2 = (cirq.CircuitOperation( cirq.FrozenCircuit(cirq.measure(a, key='P'), op1)).with_measurement_key_mapping({ 'B': 'C', 'P': 'Q' }).repeat(2, ['zero', 'one'])) op3 = (cirq.CircuitOperation( cirq.FrozenCircuit(cirq.measure(a, key='X'), op2)).with_measurement_key_mapping({ 'C': 'D', 'X': 'Y' }).repeat(2, ['zero', 'one'])) expected_circuit = cirq.Circuit( cirq.measure(a, key='zero-Y'), cirq.measure(a, key='zero-zero-Q'), cirq.measure(a, key='zero-zero-zero-D'), cirq.measure(a, key='zero-zero-one-D'), cirq.measure(a, key='zero-one-Q'), cirq.measure(a, key='zero-one-zero-D'), cirq.measure(a, key='zero-one-one-D'), cirq.measure(a, key='one-Y'), cirq.measure(a, key='one-zero-Q'), cirq.measure(a, key='one-zero-zero-D'), cirq.measure(a, key='one-zero-one-D'), cirq.measure(a, key='one-one-Q'), cirq.measure(a, key='one-one-zero-D'), cirq.measure(a, key='one-one-one-D'), ) assert cirq.Circuit(cirq.decompose(op3)) == expected_circuit
def test_autodecompose_deprecated(): dev = ValidatingTestDevice( allowed_qubit_types=(cirq.LineQubit, ), allowed_gates=( cirq.XPowGate, cirq.ZPowGate, cirq.CZPowGate, cirq.YPowGate, cirq.MeasurementGate, ), qubits=set(cirq.LineQubit.range(3)), name='test', validate_locality=False, auto_decompose_gates=(cirq.CCXPowGate, ), ) a, b, c = cirq.LineQubit.range(3) circuit = cirq.Circuit(cirq.CCX(a, b, c), device=dev) decomposed = cirq.decompose(cirq.CCX(a, b, c)) assert circuit.moments == cirq.Circuit(decomposed).moments with pytest.raises(ValueError, match="Unsupported gate type: cirq.TOFFOLI"): dev = ValidatingTestDevice( allowed_qubit_types=(cirq.LineQubit, ), allowed_gates=( cirq.XPowGate, cirq.ZPowGate, cirq.CZPowGate, cirq.YPowGate, cirq.MeasurementGate, ), qubits=set(cirq.LineQubit.range(3)), name='test', validate_locality=False, auto_decompose_gates=tuple(), ) a, b, c = cirq.LineQubit.range(3) cirq.Circuit(cirq.CCX(a, b, c), device=dev)
def test_layered_circuit_operations_with_controls_in_between(): q = cirq.LineQubit(0) outer_subcircuit = cirq.CircuitOperation( cirq.Circuit( cirq.CircuitOperation(cirq.FrozenCircuit( cirq.X(q), cirq.Y(q), )).with_classical_controls('m')).freeze()) circuit = outer_subcircuit.mapped_circuit(deep=True) cirq.testing.assert_has_diagram( cirq.Circuit(outer_subcircuit), """ [ 0: ───[ 0: ───X───Y─── ].with_classical_controls(m)─── ] 0: ───[ ║ ]─── [ m: ═══╩═══════════════════════════════════════════════ ] ║ m: ═══╩════════════════════════════════════════════════════════════ """, use_unicode_characters=True, ) cirq.testing.assert_has_diagram( circuit, """ 0: ───[ 0: ───X───Y─── ].with_classical_controls(m)─── ║ m: ═══╩═══════════════════════════════════════════════ """, use_unicode_characters=True, ) cirq.testing.assert_has_diagram( cirq.Circuit(cirq.decompose(outer_subcircuit)), """ 0: ───X───Y─── ║ ║ m: ═══^═══^═══ """, use_unicode_characters=True, )
def test_scope_extern_wrapping_with_non_repeating_subcircuits(): def wrap(*ops): return cirq.CircuitOperation(cirq.FrozenCircuit(*ops)) def wrap_frozen(*ops): return cirq.FrozenCircuit(wrap(*ops)) q = cirq.LineQubit(0) inner = wrap_frozen( wrap(cirq.measure(q, key='a')), wrap(cirq.X(q).with_classical_controls('b')), ) middle = wrap_frozen( wrap(cirq.measure(q, key=cirq.MeasurementKey('b'))), wrap(cirq.CircuitOperation(inner, repetitions=2)), ) outer_subcircuit = cirq.CircuitOperation(middle, repetitions=2) circuit = outer_subcircuit.mapped_circuit(deep=True) internal_control_keys = [ str(condition) for op in circuit.all_operations() for condition in cirq.control_keys(op) ] assert internal_control_keys == ['0:b', '0:b', '1:b', '1:b'] assert not cirq.control_keys(outer_subcircuit) assert not cirq.control_keys(circuit) cirq.testing.assert_has_diagram( circuit, """ 0: ─────M───M('0:0:a')───X───M('0:1:a')───X───M───M('1:0:a')───X───M('1:1:a')───X─── ║ ║ ║ ║ ║ ║ 0:b: ═══@════════════════^════════════════^═══╬════════════════╬════════════════╬═══ ║ ║ ║ 1:b: ═════════════════════════════════════════@════════════════^════════════════^═══ """, use_unicode_characters=True, ) assert circuit == cirq.Circuit(cirq.decompose(outer_subcircuit))
def test_gate_decomposition(gate: cirq.Gate, testcase: unittest.TestCase, print_circuit=True, expected_unitary=None): qubits = cirq.LineQubit.range(2) control, target = qubits circuit_compressed = cirq.Circuit() circuit_decomposed = cirq.Circuit() circuit_compressed.append(gate.on(control, target)) circuit_decomposed.append( cirq.decompose(gate.on(control, target), keep=is_a_basic_operation)) if print_circuit: print("Compressed circuit: \n{}".format(circuit_compressed)) print("Decomposed circuit: \n{}".format(circuit_decomposed)) print(cirq.unitary(circuit_compressed).round(3)) print(cirq.unitary(circuit_decomposed).round(3)) testcase.assertTrue( np.allclose((cirq.unitary(circuit_compressed) if expected_unitary is None else expected_unitary), cirq.unitary(circuit_decomposed)))
def optimize_circuit(self, circuit: circuits.Circuit): #Write qasm file from circuit circuit = Circuit( decompose(circuit, intercepting_decomposer=decompose_library, keep=need_to_keep)) qasm_str = cirq.qasm(circuit) f = open("temp.qasm", "w") f.write(qasm_str) f.close() #Call VOQC optimizations from input list and go from rzq to rz t = self.function_call("temp.qasm") rzq_to_rz("temp2.qasm") #Get Cirq Circuit from qasm file with open("temp2.qasm", "r") as f: c = f.read() circ = circuit_from_qasm(c) #Remove temporary files os.remove("temp.qasm") os.remove("temp2.qasm") return circ
def test_default_validation_and_inverse(): class TestGate(cirq.Gate): def _num_qubits_(self): return 2 def _decompose_(self, qubits): a, b = qubits yield cirq.Z(a) yield cirq.S(b) yield cirq.X(a) def __eq__(self, other): return isinstance(other, TestGate) def __repr__(self): return 'TestGate()' a, b = cirq.LineQubit.range(2) with pytest.raises(ValueError, match='number of qubits'): TestGate().on(a) t = TestGate().on(a, b) i = t**-1 assert i**-1 == t assert t**-1 == i assert cirq.decompose(i) == [cirq.X(a), cirq.S(b)**-1, cirq.Z(a)] cirq.testing.assert_allclose_up_to_global_phase( cirq.unitary(i), cirq.unitary(t).conj().T, atol=1e-8) cirq.testing.assert_implements_consistent_protocols( i, local_vals={'TestGate': TestGate})
def test_decompose(): qreg = cirq.LineQubit.range(3) op = cirq.ParallelGateOperation(cirq.X, qreg) assert cirq.decompose(op) == cirq.X.on_each(*qreg)
def test_decompose_nested(): a, b, c, d = cirq.LineQubit.range(4) exp1 = sympy.Symbol('exp1') exp_half = sympy.Symbol('exp_half') exp_one = sympy.Symbol('exp_one') exp_two = sympy.Symbol('exp_two') circuit1 = cirq.FrozenCircuit(cirq.X(a)**exp1, cirq.measure(a, key='m1')) op1 = cirq.CircuitOperation(circuit1) circuit2 = cirq.FrozenCircuit( op1.with_qubits(a).with_measurement_key_mapping({'m1': 'ma'}), op1.with_qubits(b).with_measurement_key_mapping({'m1': 'mb'}), op1.with_qubits(c).with_measurement_key_mapping({'m1': 'mc'}), op1.with_qubits(d).with_measurement_key_mapping({'m1': 'md'}), ) op2 = cirq.CircuitOperation(circuit2) circuit3 = cirq.FrozenCircuit( op2.with_params({exp1: exp_half}), op2.with_params({ exp1: exp_one }).with_measurement_key_mapping({ 'ma': 'ma1' }).with_measurement_key_mapping({ 'mb': 'mb1' }).with_measurement_key_mapping({ 'mc': 'mc1' }).with_measurement_key_mapping({'md': 'md1'}), op2.with_params({ exp1: exp_two }).with_measurement_key_mapping({ 'ma': 'ma2' }).with_measurement_key_mapping({ 'mb': 'mb2' }).with_measurement_key_mapping({ 'mc': 'mc2' }).with_measurement_key_mapping({'md': 'md2'}), ) op3 = cirq.CircuitOperation(circuit3) final_op = op3.with_params({exp_half: 0.5, exp_one: 1.0, exp_two: 2.0}) expected_circuit1 = cirq.Circuit( op2.with_params({ exp1: 0.5, exp_half: 0.5, exp_one: 1.0, exp_two: 2.0 }), op2.with_params({ exp1: 1.0, exp_half: 0.5, exp_one: 1.0, exp_two: 2.0 }).with_measurement_key_mapping({ 'ma': 'ma1' }).with_measurement_key_mapping({ 'mb': 'mb1' }).with_measurement_key_mapping({ 'mc': 'mc1' }).with_measurement_key_mapping({'md': 'md1'}), op2.with_params({ exp1: 2.0, exp_half: 0.5, exp_one: 1.0, exp_two: 2.0 }).with_measurement_key_mapping({ 'ma': 'ma2' }).with_measurement_key_mapping({ 'mb': 'mb2' }).with_measurement_key_mapping({ 'mc': 'mc2' }).with_measurement_key_mapping({'md': 'md2'}), ) result_ops1 = cirq.decompose_once(final_op) assert cirq.Circuit(result_ops1) == expected_circuit1 expected_circuit = cirq.Circuit( cirq.X(a)**0.5, cirq.measure(a, key='ma'), cirq.X(b)**0.5, cirq.measure(b, key='mb'), cirq.X(c)**0.5, cirq.measure(c, key='mc'), cirq.X(d)**0.5, cirq.measure(d, key='md'), cirq.X(a)**1.0, cirq.measure(a, key='ma1'), cirq.X(b)**1.0, cirq.measure(b, key='mb1'), cirq.X(c)**1.0, cirq.measure(c, key='mc1'), cirq.X(d)**1.0, cirq.measure(d, key='md1'), cirq.X(a)**2.0, cirq.measure(a, key='ma2'), cirq.X(b)**2.0, cirq.measure(b, key='mb2'), cirq.X(c)**2.0, cirq.measure(c, key='mc2'), cirq.X(d)**2.0, cirq.measure(d, key='md2'), ) assert cirq.Circuit(cirq.decompose(final_op)) == expected_circuit # Verify that mapped_circuit gives the same operations. assert final_op.mapped_circuit(deep=True) == expected_circuit
def test_decompose(): a = cirq.NamedQubit('a') b = cirq.NamedQubit('b') m = cirq.Moment(cirq.X(a), cirq.X(b)) assert list(cirq.decompose(m)) == list(m.operations)
def add_swap_test( state1: typing.Union[cirq.Qid, typing.Iterable[cirq.Qid]], state2: typing.Union[cirq.Qid, typing.Iterable[cirq.Qid]], circuit: cirq.Circuit, auxiliary_qubit: typing.Optional[cirq.Qid] = None, auxiliary_qubit_type: typing.Optional[ typing.Union[typing.Type[cirq.GridQubit], typing.Type[cirq.LineQubit]] ] = cirq.GridQubit, cswap_in_elementary_gates: bool = False ) -> typing.Tuple[str, cirq.Qid]: """ Add a SWAP test between two quantum states `state1` and `state2`, and then add the test into `circuit`. 999: ───H───@───H───M('SWAP test measure')─── │ 1: ─────────SWAP───────────────────────────── │ 2: ─────────SWAP───────────────────────────── :param state1: Quantum state to be tested. :param state2: Quantum state to be tested. :param circuit: The quantum circuit to which the SWAP test is to be appended. :param auxiliary_qubit: The auxiliary qubit. If being None, it will be created by `generate_auxiliary_qubit`. If being a `cirq.Qid` object, then it will be used as the auxiliary qubit of our SWAP test, and the argument `auxiliary_qubit_type` will be ignored. Note: `auxiliary_qubit` and `auxiliary_qubit_type` can not both be `None` at the same time. :param auxiliary_qubit_type: The type of the auxiliary qubit of SWAP test. Only LineQubit and GridQubit are supported. If `auxiliary_qubit` is None, this argument will be used to create the auxiliary qubit. If `auxiliary_qubit` is a `cirq.Qid` object, then this argument will be ignored. Note: `auxiliary_qubit` and `auxiliary_qubit_type` can not both be `None` at the same time. :param cswap_in_elementary_gates: Tells whether the CSWAP gate will be represented in elementary gates. :return: The string key of the measurement. """ if isinstance(state1, cirq.Qid): state1 = [state1] if isinstance(state2, cirq.Qid): state2 = [state2] if len(state1) != len(state2): raise ValueError( "Qubit lengths of the two target states must equal, " "but {} != {}.".format(len(state1), len(state2)) ) if auxiliary_qubit is None: auxiliary_qubit = generate_auxiliary_qubit(circuit, auxiliary_qubit_type) measurement_name = "SWAP test measure " existed_swap_measurement_ids = {int(key[len(measurement_name):]) for key in get_all_measurement_keys(circuit) if key.startswith(measurement_name)} swap_measurement_id = (max(existed_swap_measurement_ids) + 1 if len(existed_swap_measurement_ids) != 0 else 0) measurement_name += str(swap_measurement_id) circuit.append(cirq.H(auxiliary_qubit)) for qubit1, qubit2 in zip(state1, state2): cswap_op = cirq.CSWAP.on(auxiliary_qubit, qubit1, qubit2) if cswap_in_elementary_gates: circuit.append( cirq.decompose(cswap_op) ) else: circuit.append(cswap_op) circuit.append([ cirq.H(auxiliary_qubit), cirq.measure(auxiliary_qubit, key=measurement_name) ]) return measurement_name, auxiliary_qubit
def test_parameterized_repeat_side_effects(): q = cirq.LineQubit(0) op = cirq.CircuitOperation( cirq.FrozenCircuit( cirq.X(q).with_classical_controls('c'), cirq.measure(q, key='m')), repetitions=sympy.Symbol('a'), ) # Control keys can be calculated because they only "lift" if there's a matching # measurement, in which case they're not returned here. assert cirq.control_keys(op) == {cirq.MeasurementKey('c')} # "local" params do not bind to the repetition param. assert cirq.parameter_names(op.with_params({'a': 1})) == {'a'} # Check errors that require unrolling the circuit. with pytest.raises( ValueError, match='Cannot unroll circuit due to nondeterministic repetitions'): cirq.measurement_key_objs(op) with pytest.raises( ValueError, match='Cannot unroll circuit due to nondeterministic repetitions'): cirq.measurement_key_names(op) with pytest.raises( ValueError, match='Cannot unroll circuit due to nondeterministic repetitions'): op.mapped_circuit() with pytest.raises( ValueError, match='Cannot unroll circuit due to nondeterministic repetitions'): cirq.decompose(op) # Not compatible with repetition ids with pytest.raises(ValueError, match='repetition ids with parameterized repetitions'): op.with_repetition_ids(['x', 'y']) with pytest.raises(ValueError, match='repetition ids with parameterized repetitions'): op.repeat(repetition_ids=['x', 'y']) # TODO(daxfohl): This should work, but likely requires a new protocol that returns *just* the # name of the measurement keys. (measurement_key_names returns the full serialized string). with pytest.raises( ValueError, match='Cannot unroll circuit due to nondeterministic repetitions'): cirq.with_measurement_key_mapping(op, {'m': 'm2'}) # Everything should work once resolved op = cirq.resolve_parameters(op, {'a': 2}) assert set(map(str, cirq.measurement_key_objs(op))) == {'0:m', '1:m'} assert op.mapped_circuit() == cirq.Circuit( cirq.X(q).with_classical_controls('c'), cirq.measure(q, key=cirq.MeasurementKey.parse_serialized('0:m')), cirq.X(q).with_classical_controls('c'), cirq.measure(q, key=cirq.MeasurementKey.parse_serialized('1:m')), ) assert cirq.decompose(op) == cirq.decompose( cirq.Circuit( cirq.X(q).with_classical_controls('c'), cirq.measure(q, key=cirq.MeasurementKey.parse_serialized('0:m')), cirq.X(q).with_classical_controls('c'), cirq.measure(q, key=cirq.MeasurementKey.parse_serialized('1:m')), ))
def test_sympy_scope(): q = cirq.LineQubit(0) a, b, c, d = sympy.symbols('a b c d') inner = cirq.Circuit( cirq.measure(q, key='a'), cirq.X(q).with_classical_controls(a & b).with_classical_controls(c | d), ) middle = cirq.Circuit( cirq.measure(q, key='b'), cirq.measure(q, key=cirq.MeasurementKey('c', ('0', ))), cirq.CircuitOperation(inner.freeze(), repetitions=2), ) outer_subcircuit = cirq.CircuitOperation(middle.freeze(), repetitions=2) circuit = outer_subcircuit.mapped_circuit(deep=True) internal_controls = [ str(k) for op in circuit.all_operations() for k in cirq.control_keys(op) ] assert set(internal_controls) == { '0:0:a', '0:1:a', '1:0:a', '1:1:a', '0:b', '1:b', 'c', 'd' } assert cirq.control_keys(outer_subcircuit) == {'c', 'd'} assert cirq.control_keys(circuit) == {'c', 'd'} assert circuit == cirq.Circuit(cirq.decompose(outer_subcircuit)) cirq.testing.assert_has_diagram( cirq.Circuit(outer_subcircuit), """ [ [ 0: ───M───X(conditions=[c | d, a & b])─── ] ] [ [ ║ ║ ] ] [ [ a: ═══@═══^══════════════════════════════ ] ] [ [ ║ ] ] [ 0: ───M───M('0:c')───[ b: ═══════^══════════════════════════════ ]──────────── ] [ ║ [ ║ ] ] [ ║ [ c: ═══════^══════════════════════════════ ] ] 0: ───[ ║ [ ║ ] ]──────────── [ ║ [ d: ═══════^══════════════════════════════ ](loops=2) ] [ ║ ║ ] [ b: ═══@══════════════╬════════════════════════════════════════════════════════ ] [ ║ ] [ c: ══════════════════╬════════════════════════════════════════════════════════ ] [ ║ ] [ d: ══════════════════╩════════════════════════════════════════════════════════ ](loops=2) ║ c: ═══╬═════════════════════════════════════════════════════════════════════════════════════════════ ║ d: ═══╩═════════════════════════════════════════════════════════════════════════════════════════════ """, use_unicode_characters=True, ) # pylint: disable=line-too-long cirq.testing.assert_has_diagram( circuit, """ 0: ───────M───M('0:0:c')───M───X(conditions=[c | d, 0:0:a & 0:b])───M───X(conditions=[c | d, 0:1:a & 0:b])───M───M('1:0:c')───M───X(conditions=[c | d, 1:0:a & 1:b])───M───X(conditions=[c | d, 1:1:a & 1:b])─── ║ ║ ║ ║ ║ ║ ║ ║ ║ ║ 0:0:a: ═══╬════════════════@═══^════════════════════════════════════╬═══╬════════════════════════════════════╬════════════════╬═══╬════════════════════════════════════╬═══╬════════════════════════════════════ ║ ║ ║ ║ ║ ║ ║ ║ ║ 0:1:a: ═══╬════════════════════╬════════════════════════════════════@═══^════════════════════════════════════╬════════════════╬═══╬════════════════════════════════════╬═══╬════════════════════════════════════ ║ ║ ║ ║ ║ ║ ║ ║ 0:b: ═════@════════════════════^════════════════════════════════════════^════════════════════════════════════╬════════════════╬═══╬════════════════════════════════════╬═══╬════════════════════════════════════ ║ ║ ║ ║ ║ ║ ║ 1:0:a: ════════════════════════╬════════════════════════════════════════╬════════════════════════════════════╬════════════════@═══^════════════════════════════════════╬═══╬════════════════════════════════════ ║ ║ ║ ║ ║ ║ 1:1:a: ════════════════════════╬════════════════════════════════════════╬════════════════════════════════════╬════════════════════╬════════════════════════════════════@═══^════════════════════════════════════ ║ ║ ║ ║ ║ 1:b: ══════════════════════════╬════════════════════════════════════════╬════════════════════════════════════@════════════════════^════════════════════════════════════════^════════════════════════════════════ ║ ║ ║ ║ c: ════════════════════════════^════════════════════════════════════════^═════════════════════════════════════════════════════════^════════════════════════════════════════^════════════════════════════════════ ║ ║ ║ ║ d: ════════════════════════════^════════════════════════════════════════^═════════════════════════════════════════════════════════^════════════════════════════════════════^════════════════════════════════════ """, use_unicode_characters=True, )
def _base_iterator(self, circuit, qubit_order, initial_state, perform_measurements=True): qubits = cirq.QubitOrder.as_qubit_order(qubit_order).order_for( circuit.all_qubits()) num_qubits = len(qubits) qid_shape = cirq.qid_shape(qubits) qubit_map = {q: i for i, q in enumerate(qubits)} if isinstance(initial_state, int): state_val = initial_state else: state_val = cirq.big_endian_digits_to_int(initial_state, base=qid_shape) state = np.array(list( cirq.big_endian_int_to_digits(state_val, base=qid_shape)), dtype=np.uint8) if len(circuit) == 0: yield ClassicalSimulatorStep(state, {}, qubit_map) def on_stuck(bad_op): return TypeError( "Can't simulate unknown operations that don't specify a " "unitary or a decomposition. {!r}".format(bad_op)) def keep(op): return ((cirq.num_qubits(op) <= 32 and (cirq.has_unitary(op) or cirq.has_mixture(op))) or cirq.is_measurement(op) or isinstance(op.gate, cirq.ResetChannel)) def simulate_op(op, temp_state): indices = [qubit_map[q] for q in op.qubits] if isinstance(op.gate, cirq.ResetChannel): self._simulate_reset(op, temp_state, indices) elif cirq.is_measurement(op): if perform_measurements: self._simulate_measurement(op, temp_state, indices, measurements) else: decomp_ops = cirq.decompose_once(op, default=None) if decomp_ops is None: self._simulate_from_matrix(op, temp_state, indices) else: try: temp2_state = temp_state.copy() for sub_op in cirq.flatten_op_tree(decomp_ops): simulate_op(sub_op, temp2_state) temp_state[...] = temp2_state except ValueError: # Non-classical unitary in the decomposition self._simulate_from_matrix(op, temp_state, indices) for moment in circuit: measurements = defaultdict(list) known_ops = cirq.decompose(moment, keep=keep, on_stuck_raise=on_stuck) for op in known_ops: simulate_op(op, state) yield ClassicalSimulatorStep(state.copy(), measurements, qubit_map)
def op_grad( operation: cirq.GateOperation, parameter: sympy.Symbol ) -> typing.Union[LinearCombinationOfOperations, GradNotImplemented]: if not cirq.is_parameterized(operation): return ZERO_OP.copy() gate = operation.gate qubits = operation.qubits if isinstance(gate, cirq.XPowGate): # dXPow(e=f(t), s) / dt = i π (s + 1 / 2 - X / 2) * (df(t)/dt) XPow(e=f(t), s) # Note that: Rx(θ) = XPowGate(exponent=θ/pi, global_shift=-0.5) partial = sympy.diff(gate.exponent, parameter) coeff_i = 1.0j * sympy.pi * (gate._global_shift + 0.5) coeff_x = -1.0j / 2 * sympy.pi if partial == 0: return ZERO_OP.copy() return LinearCombinationOfOperations({ (cirq.X.on(*qubits), operation): coeff_x * partial, (cirq.I.on(*qubits), operation): coeff_i * partial }) elif isinstance(gate, cirq.YPowGate): # dYPow(e=f(t), s) / dt = i π (s + 1 / 2 - Y / 2) * (df(t)/dt) YPow(e=f(t), s) # Note that: Ry(θ) = YPowGate(exponent=θ/pi, global_shift=-0.5) partial = sympy.diff(gate.exponent, parameter) coeff_i = 1.0j * sympy.pi * (gate._global_shift + 0.5) coeff_y = -1.0j / 2 * sympy.pi if partial == 0: return ZERO_OP.copy() return LinearCombinationOfOperations({ (cirq.Y.on(*qubits), operation): coeff_y * partial, (cirq.I.on(*qubits), operation): coeff_i * partial }) elif isinstance(gate, cirq.ZPowGate): # dZPow(e=f(t), s) / dt = i π (s + 1 / 2 - Z / 2) * (df(t)/dt) ZPow(e=f(t), s) # Note that: Ry(θ) = ZPowGate(exponent=θ/pi, global_shift=-0.5) partial = sympy.diff(gate.exponent, parameter) coeff_i = 1.0j * sympy.pi * (gate._global_shift + 0.5) coeff_z = -1.0j / 2 * sympy.pi if partial == 0: return ZERO_OP.copy() return LinearCombinationOfOperations({ (cirq.Z.on(*qubits), operation): coeff_z * partial, (cirq.I.on(*qubits), operation): coeff_i * partial }) elif isinstance(gate, GlobalPhaseGate): gate = typing.cast(GlobalPhaseGate, gate) # Ph(θ) = exp(i pi θ) # dPh(f(θ)) / dθ = [i pi df(θ) / dθ] exp(i pi f(θ)) # = [i pi df(θ) / dθ] Ph(f(θ)) coeff = 1.0j * sympy.diff(gate.rad * sympy.pi, parameter) if coeff == 0: return ZERO_OP.copy() return LinearCombinationOfOperations({(operation, ): coeff}) elif isinstance(gate, cirq.EigenGate): gate = typing.cast(cirq.EigenGate, gate) eigenvalues = {v for v, p in gate._eigen_components()} if eigenvalues == {0, 1}: e = gate.exponent s = gate._global_shift partial = sympy.diff(e, parameter) if partial == 0: return ZERO_OP.copy() num_qubits = gate.num_qubits() gate_e1_s0 = copy.deepcopy(gate) gate_e1_s0._exponent = 1.0 gate_e1_s0._global_shift = 0.0 # Any better solutions? coeff = 0.5 * sympy.exp(1.0j * sympy.pi * (1 + s) * e) return 1.0j * sympy.pi * LinearCombinationOfOperations( { (operation, ): s * partial, (gate_e1_s0.on(*qubits), ): -coeff * partial, (cirq.IdentityGate(num_qubits).on(*qubits), ): coeff * partial }) else: return GradNotImplemented(operation) elif isinstance(gate, GateBlock): gate = typing.cast(GateBlock, gate) generator_grad = op_tree_generator_grad(gate._op_generator, parameter) if isinstance(generator_grad, GradNotImplemented): return generator_grad if len(generator_grad) == 0: return ZERO_OP.copy() _grad = LinearCombinationOfOperations({}) for generator, coeff in generator_grad.items(): grad_gate = GateBlock(generator) _grad += LinearCombinationOfOperations({ (grad_gate.on(*qubits), ): coeff }) # print(grad_gate.diagram()) return _grad elif isinstance(gate, cirq.ControlledGate): gate = typing.cast(cirq.ControlledGate, gate) sub_gate_qubits = qubits[gate.num_controls():] sub_op_grad = op_grad(gate.sub_gate.on(*sub_gate_qubits), parameter) if is_zero_op_or_grad_not_implemented(sub_op_grad): return sub_op_grad _gate_grad = LinearCombinationOfOperations({}) op: cirq.GateOperation for op_series, coeff in sub_op_grad.items(): _controlled_op_series = [ cirq.ControlledGate( op.gate, control_qubits=qubits[:gate.num_controls()]).on( *sub_gate_qubits) for op in op_series ] _controlled_negative_op_series = copy.deepcopy( _controlled_op_series) _controlled_negative_op_series.insert( 0, cirq.ControlledGate( GlobalPhaseGate(rad=1), control_qubits=qubits[:gate.num_controls()]).on( *sub_gate_qubits)) _gate_grad += LinearCombinationOfOperations( { tuple(_controlled_op_series): coeff, tuple(_controlled_negative_op_series): -coeff, }) / 2.0 return _gate_grad # if `operation` is a basic and indecomposable operation whose grad is # not implemented elif is_an_indecomposable_operation(operation): return GradNotImplemented(operation) else: op_series = cirq.decompose( operation, keep=(lambda op: is_a_basic_operation(op) or is_an_indecomposable_operation(op)), on_stuck_raise=None) # type: typing.List[cirq.Operation] _grad = op_series_grad(op_series, parameter) return _grad
def test_decomposition_cost(op: cirq.Operation, max_two_cost: int): ops = tuple(cirq.flatten_op_tree(cirq.decompose(op))) two_cost = len([e for e in ops if len(e.qubits) == 2]) over_cost = len([e for e in ops if len(e.qubits) > 2]) assert over_cost == 0 assert two_cost == max_two_cost
x_train_circ = [encode_to_circuit(x) for x in train_x] x_test_circ = [encode_to_circuit(x) for x in test_x] # Convert input-data circuits to tensors x_train_tfcirc = tfq.convert_to_tensor(x_train_circ) x_test_tfcirc = tfq.convert_to_tensor(x_test_circ) # Make the rest of the circuit that applies the weights and U-gate qubits = cirq.GridQubit.rect(2, 2) C1, C2, T1, T2 = qubits model_circuit = cirq.Circuit() # First set of weights: w w = sp.symbols('w:11') gamma_encode(model_circuit, C2, T2, *w) # Apply U-gate t = sp.symbols('t') u = cirq.decompose(U(t).on(qubits[0], qubits[1])) print(cirq.to_json(u)) model_circuit.append(u) # Assign readout qubits model_readout = cirq.Z(C2) # Make parametrized circuit model poc = tfq.layers.PQC(model_circuit, model_readout) # Build the model model = tf.keras.Sequential( [tf.keras.layers.Input(shape=(), dtype=tf.string), poc])
def test_tagged_operation_forwards_protocols(): """The results of all protocols applied to an operation with a tag should be equivalent to the result without tags. """ q1 = cirq.GridQubit(1, 1) q2 = cirq.GridQubit(1, 2) h = cirq.H(q1) tag = 'tag1' tagged_h = cirq.H(q1).with_tags(tag) np.testing.assert_equal(cirq.unitary(tagged_h), cirq.unitary(h)) assert cirq.has_unitary(tagged_h) assert cirq.decompose(tagged_h) == cirq.decompose(h) assert cirq.pauli_expansion(tagged_h) == cirq.pauli_expansion(h) assert cirq.equal_up_to_global_phase(h, tagged_h) assert np.isclose(cirq.channel(h), cirq.channel(tagged_h)).all() assert cirq.measurement_key(cirq.measure(q1, key='blah').with_tags(tag)) == 'blah' parameterized_op = cirq.XPowGate(exponent=sympy.Symbol('t'))(q1).with_tags(tag) assert cirq.is_parameterized(parameterized_op) resolver = cirq.study.ParamResolver({'t': 0.25}) assert cirq.resolve_parameters(parameterized_op, resolver) == cirq.XPowGate(exponent=0.25)( q1 ).with_tags(tag) assert cirq.resolve_parameters_once(parameterized_op, resolver) == cirq.XPowGate(exponent=0.25)( q1 ).with_tags(tag) y = cirq.Y(q1) tagged_y = cirq.Y(q1).with_tags(tag) assert tagged_y ** 0.5 == cirq.YPowGate(exponent=0.5)(q1) assert tagged_y * 2 == (y * 2) assert 3 * tagged_y == (3 * y) assert cirq.phase_by(y, 0.125, 0) == cirq.phase_by(tagged_y, 0.125, 0) controlled_y = tagged_y.controlled_by(q2) assert controlled_y.qubits == ( q2, q1, ) assert isinstance(controlled_y, cirq.Operation) assert not isinstance(controlled_y, cirq.TaggedOperation) clifford_x = cirq.SingleQubitCliffordGate.X(q1) tagged_x = cirq.SingleQubitCliffordGate.X(q1).with_tags(tag) assert cirq.commutes(clifford_x, clifford_x) assert cirq.commutes(tagged_x, clifford_x) assert cirq.commutes(clifford_x, tagged_x) assert cirq.commutes(tagged_x, tagged_x) assert cirq.trace_distance_bound(y ** 0.001) == cirq.trace_distance_bound( (y ** 0.001).with_tags(tag) ) flip = cirq.bit_flip(0.5)(q1) tagged_flip = cirq.bit_flip(0.5)(q1).with_tags(tag) assert cirq.has_mixture(tagged_flip) assert cirq.has_channel(tagged_flip) flip_mixture = cirq.mixture(flip) tagged_mixture = cirq.mixture(tagged_flip) assert len(tagged_mixture) == 2 assert len(tagged_mixture[0]) == 2 assert len(tagged_mixture[1]) == 2 assert tagged_mixture[0][0] == flip_mixture[0][0] assert np.isclose(tagged_mixture[0][1], flip_mixture[0][1]).all() assert tagged_mixture[1][0] == flip_mixture[1][0] assert np.isclose(tagged_mixture[1][1], flip_mixture[1][1]).all() qubit_map = {q1: 'q1'} qasm_args = cirq.QasmArgs(qubit_id_map=qubit_map) assert cirq.qasm(h, args=qasm_args) == cirq.qasm(tagged_h, args=qasm_args) cirq.testing.assert_has_consistent_apply_unitary(tagged_h)
def translate_cirq_to_qsim( self, qubit_order: cirq.ops.QubitOrderOrList = cirq.ops.QubitOrder.DEFAULT ) -> qsim.Circuit: """ Translates this Cirq circuit to the qsim representation. :qubit_order: Ordering of qubits :return: a C++ qsim Circuit object """ qsim_circuit = qsim.Circuit() qsim_circuit.num_qubits = len(self.all_qubits()) ordered_qubits = cirq.ops.QubitOrder.as_qubit_order(qubit_order).order_for( self.all_qubits()) # qsim numbers qubits in reverse order from cirq ordered_qubits = list(reversed(ordered_qubits)) def has_qsim_kind(op: cirq.ops.GateOperation): return _cirq_gate_kind(op.gate) != None def to_matrix(op: cirq.ops.GateOperation): mat = cirq.protocols.unitary(op.gate, None) if mat is None: return NotImplemented return cirq.ops.MatrixGate(mat).on(*op.qubits) qubit_to_index_dict = {q: i for i, q in enumerate(ordered_qubits)} time_offset = 0 for moment in self: ops_by_gate = [ cirq.decompose(op, fallback_decomposer=to_matrix, keep=has_qsim_kind) for op in moment ] moment_length = max(len(gate_ops) for gate_ops in ops_by_gate) # Gates must be added in time order. for gi in range(moment_length): for gate_ops in ops_by_gate: if gi >= len(gate_ops): continue qsim_op = gate_ops[gi] gate_kind = _cirq_gate_kind(qsim_op.gate) time = time_offset + gi qubits = [qubit_to_index_dict[q] for q in qsim_op.qubits] qsim_gate = qsim_op.gate qsim_qubits = qubits is_controlled = isinstance(qsim_op.gate, cirq.ops.ControlledGate) if is_controlled: control_qubits, control_values = _control_details(qsim_op.gate, qubits) if control_qubits is None: # This gate has no valid control, and will be omitted. continue if qsim_gate.num_qubits() > 4: raise NotImplementedError( f'Received control gate on {gate.num_qubits()} target qubits; ' + 'only up to 4-qubit gates are supported.') qsim_gate = qsim_gate.sub_gate qsim_qubits = qubits[qsim_op.gate.num_controls():] if gate_kind == qsim.kTwoQubitDiagonalGate or gate_kind == qsim.kThreeQubitDiagonalGate: qsim.add_diagonal_gate(time, qsim_qubits, qsim_gate._diag_angles_radians, qsim_circuit) elif gate_kind == qsim.kMatrixGate: flatten = lambda l : [val for i in l for val in [i.real, i.imag]] qsim.add_matrix_gate(time, qsim_qubits, flatten(list(cirq.unitary(qsim_gate).flat)), qsim_circuit) else: params = { p.strip('_'): val for p, val in vars(qsim_gate).items() if isinstance(val, float) or isinstance(val, int) } qsim.add_gate(gate_kind, time, qsim_qubits, params, qsim_circuit) if is_controlled: qsim.control_last_gate(control_qubits, control_values, qsim_circuit) time_offset += moment_length return qsim_circuit