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_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_two_qubit_gates(qasm_gate: str, cirq_gate: cirq.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_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_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_unsupported_format(): qasm = "OPENQASM 2.1;" parser = QasmParser() with pytest.raises(QasmException, match="Unsupported.*2.1.*2.0.*supported.*"): parser.parse(qasm)
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_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_unsupported_format(): qasm = "OPENQASM 2.1;" parser = QasmParser() with pytest.raises(QasmException, match="Unsupported OpenQASM version: 2.1, " "only 2.0 is supported currently by Cirq"): parser.parse(qasm)
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_qelib_gate_without_include_statement(): qasm = """OPENQASM 2.0; qreg q[2]; x q[0]; """ parser = QasmParser() with pytest.raises(QasmException, match=r"""Unknown gate "x".* line 3.*forget.*\?"""): parser.parse(qasm)
def test_undefined_register_from_qubit_arg(): qasm = """OPENQASM 2.0; qreg q[2]; CX q[0], q2[1]; """ parser = QasmParser() with pytest.raises(QasmException, match=r"""Undefined.*register.*q2.*"""): parser.parse(qasm)
def test_U_gate_too_much_params_error(): qasm = """OPENQASM 2.0; qreg q[2]; U(pi, pi, pi, pi) q[1];""" parser = QasmParser() with pytest.raises(QasmException, match=r"U takes 3.*got.*4.*line 3"): parser.parse(qasm)
def test_unknown_function(): qasm = """OPENQASM 2.0; qreg q[1]; U(nonexistent(3), 2 * pi, pi / 3.0) q[0]; """ parser = QasmParser() with pytest.raises(QasmException, match=r".*not recognized.*'nonexistent'.*line 3"): parser.parse(qasm)
def test_CX_gate_not_enough_args(): qasm = """OPENQASM 2.0; qreg q[2]; CX q[0]; """ parser = QasmParser() with pytest.raises(QasmException, match=r"CX.*takes.*got.*1.*line 3"): parser.parse(qasm)
def test_unexpected_end_of_file(): qasm = """OPENQASM 2.0; include "qelib1.inc"; creg """ parser = QasmParser() with pytest.raises(QasmException, match="Unexpected end of file"): parser.parse(qasm)
def test_syntax_error(): qasm = """OPENQASM 2.0; qreg q[2] bla; foobar q[0]; """ parser = QasmParser() with pytest.raises(QasmException, match=r"""Syntax error: 'bla'.*"""): parser.parse(qasm)
def test_CX_gate_arg_overlap(): qasm = """OPENQASM 2.0; qreg q1[2]; qreg q2[3]; CX q1[1], q1[1]; """ parser = QasmParser() with pytest.raises(QasmException, match=r"Overlapping.*at line 4"): parser.parse(qasm)
def test_u_gate_zero_params_error(): qasm = """OPENQASM 2.0; qreg q[2]; U() q[1];""" parser = QasmParser() with pytest.raises(QasmException, match=r"U takes 3 parameter\(s\).*got.*0.*line 3"): parser.parse(qasm)
def test_measurement_bounds(): qasm = """OPENQASM 2.0; qreg q1[3]; creg c1[3]; measure q1[0] -> c1[4]; """ parser = QasmParser() with pytest.raises(QasmException, match=r"Out of bounds bit.*4.*c1.*size 3.*line 4"): parser.parse(qasm)
def test_CX_gate_mismatched_registers(): qasm = """OPENQASM 2.0; qreg q1[2]; qreg q2[3]; CX q1, q2; """ parser = QasmParser() with pytest.raises(QasmException, match=r"Non matching.*length \[2 3\].*line 4"): parser.parse(qasm)
def test_CX_gate_bounds(): qasm = """OPENQASM 2.0; qreg q1[2]; qreg q2[3]; CX q1[4], q2[0]; """ parser = QasmParser() with pytest.raises(QasmException, match=r"Out of bounds.*4.*q1.*2.*line 4"): parser.parse(qasm)
def test_unknown_basic_gate(): qasm = """OPENQASM 2.0; qreg q[2]; foobar q[0]; """ parser = QasmParser() with pytest.raises( QasmException, match=r"""Unknown gate "foobar".* line 3.*forgot.*\?"""): parser.parse(qasm)
def test_three_qubit_gates_with_too_much_parameters(qasm_gate: str): qasm = f"""OPENQASM 2.0; include "qelib1.inc"; qreg q[3]; {qasm_gate}(pi) q[0],q[1],q[2]; """ parser = QasmParser() with pytest.raises(QasmException, match=r""".*{}.*parameter.*line 4.*""".format(qasm_gate)): parser.parse(qasm)
def test_rotation_gates_zero_params_error(qasm_gate: str): qasm = f"""OPENQASM 2.0; include "qelib1.inc"; qreg q[2]; {qasm_gate} q[1]; """ parser = QasmParser() with pytest.raises(QasmException, match=r".*{}.* takes 1.*got.*0.*line 4".format(qasm_gate)): parser.parse(qasm)
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_CX_gate_not_enough_args(): qasm = """OPENQASM 2.0; qreg q[2]; CX q[0]; """ parser = QasmParser() with pytest.raises(QasmException, match=(r"CX only takes 2 arg\(s\) " r"\(qubits and/or registers\)" r", got: 1, at line 3")): parser.parse(qasm)
def test_measurement_bounds(): qasm = """OPENQASM 2.0; qreg q1[3]; creg c1[3]; measure q1[0] -> c1[4]; """ parser = QasmParser() with pytest.raises(QasmException, match=r"Out of bounds bit index 4" r" on classical register c1 of size 3 at line 4"): parser.parse(qasm)
def test_cx_gate_bounds(): qasm = """OPENQASM 2.0; qreg q1[2]; qreg q2[3]; CX q1[4], q2[0]; """ parser = QasmParser() with pytest.raises(QasmException, match=r"Out of bounds qubit index 4" r" on register q1 of size 2 at line 4"): parser.parse(qasm)
def test_standard_single_qubit_gates_wrong_number_of_args(qasm_gate): qasm = f""" OPENQASM 2.0; include "qelib1.inc"; qreg q[2]; {qasm_gate} q[0], q[1]; """ parser = QasmParser() with pytest.raises(QasmException, match=r".* takes 1.*got.*2.*line 5"): parser.parse(qasm)