def test_rotation_gates(qasm_gate: str, cirq_gate: cirq.SingleQubitGate): qasm = """OPENQASM 2.0; include "qelib1.inc"; qreg q[2]; {0}(pi/2) q[0]; {0}(pi) q; """.format(qasm_gate) parser = QasmParser() q0 = cirq.NamedQubit('q_0') q1 = cirq.NamedQubit('q_1') expected_circuit = Circuit() expected_circuit.append( cirq.Moment([cirq_gate(np.pi / 2).on(q0), cirq_gate(np.pi).on(q1)])) expected_circuit.append(cirq.Moment([ cirq_gate(np.pi).on(q0), ])) parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat assert parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit) assert parsed_qasm.qregs == {'q': 2}
def test_single_qubit_gates(qasm_gate: str, cirq_gate: cirq.SingleQubitGate): qasm = """OPENQASM 2.0; include "qelib1.inc"; qreg q[2]; {0} q[0]; {0} q; """.format(qasm_gate) parser = QasmParser() q0 = cirq.NamedQubit('q_0') q1 = cirq.NamedQubit('q_1') expected_circuit = Circuit([ cirq_gate.on(q0), cirq_gate.on(q0), cirq_gate.on(q1), ]) parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat assert parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit) assert parsed_qasm.qregs == {'q': 2}
def test_two_qubit_gates(qasm_gate: str, cirq_gate: cirq.testing.TwoQubitGate): qasm = """ OPENQASM 2.0; include "qelib1.inc"; qreg q1[2]; qreg q2[2]; {0} q1[0], q1[1]; {0} q1, q2[0]; {0} q2, q1; """.format(qasm_gate) parser = QasmParser() q1_0 = cirq.NamedQubit('q1_0') q1_1 = cirq.NamedQubit('q1_1') q2_0 = cirq.NamedQubit('q2_0') q2_1 = cirq.NamedQubit('q2_1') expected_circuit = Circuit() # CX q1[0], q1[1]; expected_circuit.append(cirq_gate(q1_0, q1_1)) # CX q1, q2[0]; expected_circuit.append(cirq_gate(q1_0, q2_0)) expected_circuit.append(cirq_gate(q1_1, q2_0)) # CX q2, q1; expected_circuit.append(cirq_gate(q2_0, q1_0)) expected_circuit.append(cirq_gate(q2_1, q1_1)) parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat assert parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit) assert parsed_qasm.qregs == {'q1': 2, 'q2': 2}
def test_u3_gate(): qasm = """ OPENQASM 2.0; include "qelib1.inc"; qreg q[2]; u3(pi, 2.3, 3) q[0]; u3(+3.14, -pi, (8)) q; """ parser = QasmParser() q0 = cirq.NamedQubit('q_0') q1 = cirq.NamedQubit('q_1') expected_circuit = Circuit() expected_circuit.append( cirq.Moment([ QasmUGate(1.0, 2.3 / np.pi, 3 / np.pi)(q0), QasmUGate(3.14 / np.pi, -1.0, 8 / np.pi)(q1), ])) expected_circuit.append( cirq.Moment([QasmUGate(3.14 / np.pi, -1.0, 8 / np.pi)(q0)])) parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat assert parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit) assert parsed_qasm.qregs == {'q': 2}
def test_measure_registers(): qasm = """OPENQASM 2.0; include "qelib1.inc"; qreg q1[3]; creg c1[3]; measure q1 -> c1; """ parser = QasmParser() q1_0 = cirq.NamedQubit('q1_0') q1_1 = cirq.NamedQubit('q1_1') q1_2 = cirq.NamedQubit('q1_2') expected_circuit = Circuit() expected_circuit.append( cirq.MeasurementGate(num_qubits=1, key='c1_0').on(q1_0)) expected_circuit.append( cirq.MeasurementGate(num_qubits=1, key='c1_1').on(q1_1)) expected_circuit.append( cirq.MeasurementGate(num_qubits=1, key='c1_2').on(q1_2)) parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat assert parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit) assert parsed_qasm.qregs == {'q1': 3} assert parsed_qasm.cregs == {'c1': 3}
def test_CX_gate(): qasm = """OPENQASM 2.0; qreg q1[2]; qreg q2[2]; CX q1[0], q1[1]; CX q1, q2[0]; CX q2, q1; """ parser = QasmParser() q1_0 = cirq.NamedQubit('q1_0') q1_1 = cirq.NamedQubit('q1_1') q2_0 = cirq.NamedQubit('q2_0') q2_1 = cirq.NamedQubit('q2_1') expected_circuit = Circuit() # CX q1[0], q1[1]; expected_circuit.append(cirq.CNOT(q1_0, q1_1)) # CX q1, q2[0]; expected_circuit.append(cirq.CNOT(q1_0, q2_0)) expected_circuit.append(cirq.CNOT(q1_1, q2_0)) # CX q2, q1; expected_circuit.append(cirq.CNOT(q2_0, q1_0)) expected_circuit.append(cirq.CNOT(q2_1, q1_1)) parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat assert not parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit) assert parsed_qasm.qregs == {'q1': 2, 'q2': 2}
def test_classical_control_multi_bit(): qasm = """OPENQASM 2.0; qreg q[2]; creg a[2]; measure q[0] -> a[0]; measure q[0] -> a[1]; if (a==1) CX q[0],q[1]; """ parser = QasmParser() q_0 = cirq.NamedQubit('q_0') q_1 = cirq.NamedQubit('q_1') # Since we split the measurement into two, we also need two conditions. # m_a==1 corresponds to m_a[0]==1, m_a[1]==0 expected_circuit = cirq.Circuit( cirq.measure(q_0, key='a_0'), cirq.measure(q_0, key='a_1'), cirq.CNOT(q_0, q_1).with_classical_controls( sympy.Eq(sympy.Symbol('a_0'), 1), sympy.Eq(sympy.Symbol('a_1'), 0) ), ) parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat assert not parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit) assert parsed_qasm.qregs == {'q': 2} # Note that this will *not* round-trip, but there's no good way around that due to the # difference in how Cirq and QASM do multi-bit measurements. with pytest.raises(ValueError, match='QASM does not support multiple conditions'): _ = cirq.qasm(parsed_qasm.circuit)
def test_format_header_circuit(): parser = QasmParser() parsed_qasm = parser.parse("OPENQASM 2.0;") assert parsed_qasm.supportedFormat is True assert not parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, Circuit())
def test_format_header_with_quelibinc_circuit(): qasm = """OPENQASM 2.0; include "qelib1.inc"; """ parser = QasmParser() parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat is True assert parsed_qasm.qelib1Include is True ct.assert_same_circuits(parsed_qasm.circuit, Circuit())
def test_multiple_qreg_declaration(): qasm = """OPENQASM 2.0; include "qelib1.inc"; qreg a_quantum_register [ 1337 ]; qreg q[42]; """ parser = QasmParser() parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat assert parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, Circuit()) assert parsed_qasm.qregs == {'a_quantum_register': 1337, 'q': 42}
def test_consistency_with_qasm_output(): a, b, c, d = [cirq.NamedQubit('q_{}'.format(i)) for i in range(4)] circuit1 = cirq.Circuit.from_ops( cirq.Rx(np.pi / 2).on(a), cirq.Ry(np.pi / 2).on(b), cirq.Rz(np.pi / 2).on(b), cirq.IdentityGate(1).on(c), cirq.circuits.qasm_output.QasmUGate(1.0, 2.0, 3.0).on(d), ) qasm1 = cirq.qasm(circuit1) circuit2 = cirq.contrib.qasm_import.qasm.QasmCircuitParser().parse(qasm1) ct.assert_same_circuits(circuit1, circuit2)
def test_comments(): parser = QasmParser() parsed_qasm = parser.parse(""" //this is the format OPENQASM 2.0; // this is some other comment include "qelib1.inc"; // and something at the end of the file // multiline """) assert parsed_qasm.supportedFormat is True assert parsed_qasm.qelib1Include is True ct.assert_same_circuits(parsed_qasm.circuit, Circuit())
def test_classical_control(): qasm = """OPENQASM 2.0; qreg q[2]; creg a[1]; measure q[0] -> a[0]; if (a==1) CX q[0],q[1]; """ parser = QasmParser() q_0 = cirq.NamedQubit('q_0') q_1 = cirq.NamedQubit('q_1') expected_circuit = cirq.Circuit( cirq.measure(q_0, key='a_0'), cirq.CNOT(q_0, q_1).with_classical_controls(sympy.Eq(sympy.Symbol('a_0'), 1)), ) parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat assert not parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit) assert parsed_qasm.qregs == {'q': 2} # Note this cannot *exactly* round-trip because the way QASM and Cirq handle measurements # into classical registers is different. Cirq parses QASM classical registers into m_a_i for i # in 0..bit_count. Thus the generated key has an extra "_0" at the end. expected_generated_qasm = f"""// Generated from Cirq v{cirq.__version__} OPENQASM 2.0; include "qelib1.inc"; // Qubits: [q_0, q_1] qreg q[2]; creg m_a_0[1]; measure q[0] -> m_a_0[0]; if (m_a_0==1) cx q[0],q[1]; """ assert cirq.qasm(parsed_qasm.circuit) == expected_generated_qasm
def test_r_gate(): qasm = """ OPENQASM 2.0; include "qelib1.inc"; qreg q[1]; r(pi, pi / 2.0) q[0]; """ parser = QasmParser() q0 = cirq.NamedQubit('q_0') expected_circuit = Circuit() expected_circuit.append(QasmUGate(1.0, 0.0, 0.0)(q0)) parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat assert parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit) assert parsed_qasm.qregs == {'q': 1}
def test_classical_control(): qasm = """OPENQASM 2.0; qreg q[2]; creg m_a[1]; measure q[0] -> m_a[0]; if (m_a!=0) CX q[0], q[1]; """ parser = QasmParser() q_0 = cirq.NamedQubit('q_0') q_1 = cirq.NamedQubit('q_1') expected_circuit = cirq.Circuit( cirq.measure(q_0, key='m_a_0'), cirq.CNOT(q_0, q_1).with_classical_controls('m_a_0')) parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat assert not parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit) assert parsed_qasm.qregs == {'q': 2}
def test_id_gate(): qasm = """ OPENQASM 2.0; include "qelib1.inc"; qreg q[2]; id q; """ parser = QasmParser() q0 = cirq.NamedQubit('q_0') q1 = cirq.NamedQubit('q_1') expected_circuit = Circuit() expected_circuit.append(cirq.IdentityGate(num_qubits=1)(q0)) expected_circuit.append(cirq.IdentityGate(num_qubits=1)(q1)) parsed_qasm = parser.parse(qasm) assert parsed_qasm.supportedFormat assert parsed_qasm.qelib1Include ct.assert_same_circuits(parsed_qasm.circuit, expected_circuit) assert parsed_qasm.qregs == {'q': 2}