def qfunc(a, b, c, angles): qml.RX(a, wires=0) qml.RX(b, wires=1) qml.PauliZ(1) qml.CNOT(wires=[0, 1]).inv() qml.CRY(b, wires=[3, 1]) qml.RX(angles[0], wires=0) qml.RX(4 * angles[1], wires=1) qml.PhaseShift(17 / 9 * c, wires=2) qml.RZ(b, wires=3) qml.RX(angles[2], wires=2).inv() qml.CRY(0.3589, wires=[3, 1]).inv() qml.CSWAP(wires=[4, 2, 1]).inv() qml.QubitUnitary(np.eye(2), wires=[2]) qml.ControlledQubitUnitary(np.eye(2), control_wires=[0, 1], wires=[2]) qml.MultiControlledX(control_wires=[0, 1, 2], wires=[3]) qml.Toffoli(wires=[0, 2, 1]) qml.CNOT(wires=[0, 2]) qml.PauliZ(wires=[1]) qml.PauliZ(wires=[1]).inv() qml.CZ(wires=[0, 1]) qml.CZ(wires=[0, 2]).inv() qml.CNOT(wires=[2, 1]) qml.CNOT(wires=[0, 2]) qml.SWAP(wires=[0, 2]).inv() qml.CNOT(wires=[1, 3]) qml.RZ(b, wires=3) qml.CSWAP(wires=[4, 0, 1]) return [ qml.expval(qml.PauliY(0)), qml.var(qml.Hadamard(wires=1)), qml.sample(qml.PauliX(2)), qml.expval(qml.Hermitian(np.eye(4), wires=[3, 4])), ]
def test_decomposition_with_custom_wire_labels(self, mocker): """Test that the decomposed MultiControlledX gate performs the same unitary as the matrix-based version by checking if U^dagger U applies the identity to each basis state. This test focuses on using custom wire labels.""" n_ctrl_wires = 4 control_wires = [-1, "alice", 42, 3.14] target_wire = ["bob"] work_wires = ["charlie"] all_wires = control_wires + target_wire + work_wires spy = mocker.spy(qml.MultiControlledX, "decomposition") dev = qml.device("default.qubit", wires=all_wires) with qml.tape.QuantumTape() as tape: qml.MultiControlledX(control_wires=control_wires, wires=target_wire, work_wires=work_wires) tape = tape.expand(depth=2) assert all(not isinstance(op, qml.MultiControlledX) for op in tape.operations) @qml.qnode(dev) def f(bitstring): qml.BasisState(bitstring, wires=control_wires + target_wire) qml.MultiControlledX(control_wires=control_wires, wires=target_wire).inv() for op in tape.operations: op.queue() return qml.probs(wires=control_wires + target_wire) u = np.array([ f(b) for b in itertools.product(range(2), repeat=n_ctrl_wires + 1) ]).T spy.assert_called() assert np.allclose(u, np.eye(2**(n_ctrl_wires + 1)))
def f(): qml.QubitStateVector(rnd_state, wires=range(n_all_wires)) qml.MultiControlledX(control_wires=control_wires, wires=target_wire).inv() for op in tape.operations: op.queue() return qml.state()
def f(bitstring): qml.BasisState(bitstring, wires=control_wires + target_wire) qml.MultiControlledX(control_wires=control_wires, wires=target_wire).inv() for op in tape.operations: op.queue() return qml.probs(wires=control_wires + target_wire)
def test_worker_state_unperturbed(self, mocker): """Test that the state of the worker wires is unperturbed after the decomposition has used them. To do this, a random state over all the qubits (control, target and workers) is loaded and U^dagger U(decomposed) is applied. If the workers are uncomputed, the output state will be the same as the input.""" control_wires = range(4) target_wire = 4 worker_wires = [5, 6] n_all_wires = 7 rnd_state = unitary_group.rvs(2**n_all_wires, random_state=1)[0] spy = mocker.spy(qml.MultiControlledX, "decomposition") dev = qml.device("default.qubit", wires=n_all_wires) with qml.tape.QuantumTape() as tape: qml.MultiControlledX(control_wires=control_wires, wires=target_wire, work_wires=worker_wires) tape = tape.expand(depth=1) assert all(not isinstance(op, qml.MultiControlledX) for op in tape.operations) @qml.qnode(dev) def f(): qml.QubitStateVector(rnd_state, wires=range(n_all_wires)) qml.MultiControlledX(control_wires=control_wires, wires=target_wire).inv() for op in tape.operations: op.queue() return qml.state() assert np.allclose(f(), rnd_state) spy.assert_called()
def test_decomposition_with_flips(self, n_ctrl_wires, control_val, mocker): """Test that the decomposed MultiControlledX gate performs the same unitary as the matrix-based version by checking if U^dagger U applies the identity to each basis state. This test focuses on varying the control values.""" control_values = control_val * n_ctrl_wires control_wires = range(n_ctrl_wires) target_wire = n_ctrl_wires work_wires = range(n_ctrl_wires + 1, 2 * n_ctrl_wires + 1) spy = mocker.spy(qml.MultiControlledX, "decomposition") dev = qml.device("default.qubit", wires=2 * n_ctrl_wires + 1) with qml.tape.QuantumTape() as tape: qml.MultiControlledX( control_wires=control_wires, wires=target_wire, work_wires=work_wires, control_values=control_values, ) tape = tape.expand(depth=1) assert all(not isinstance(op, qml.MultiControlledX) for op in tape.operations) @qml.qnode(dev) def f(bitstring): qml.BasisState(bitstring, wires=range(n_ctrl_wires + 1)) qml.MultiControlledX( control_wires=control_wires, wires=target_wire, control_values=control_values ).inv() for op in tape.operations: op.queue() return qml.probs(wires=range(n_ctrl_wires + 1)) u = np.array([f(b) for b in itertools.product(range(2), repeat=n_ctrl_wires + 1)]).T spy.assert_called() assert np.allclose(u, np.eye(2 ** (n_ctrl_wires + 1)))
def f(bitstring): qml.BasisState(bitstring, wires=range(n_ctrl_wires + 1)) qml.MultiControlledX(control_wires=control_wires, wires=target_wire, control_values=control_values).inv() for op in tape.operations: op.queue() return qml.probs(wires=range(n_ctrl_wires + 1))
def circuit_mpmct(): qml.templates.ArbitraryStatePreparation(control_state_weights, wires=control_wires) qml.templates.ArbitraryStatePreparation(target_state_weights, wires=target_wires) qml.MultiControlledX( control_wires=control_wires, wires=target_wires, control_values=control_values ) return qml.state()
def circ(): for wire in wires: qml.Hadamard(wire) for _ in range(5): qml.Hadamard(wires[0]) qml.MultiControlledX(wires=wires[0], control_wires=wires[1:]) qml.Hadamard(wires[0]) qml.templates.GroverOperator(wires=wires) return qml.probs(wires=wires)
def test_invalid_mixed_polarity_controls(self, control_wires, wires, control_values, expected_error_message): """Test if MultiControlledX properly handles invalid mixed-polarity control values.""" target_wires = Wires(wires) with pytest.raises(ValueError, match=expected_error_message): qml.MultiControlledX(control_wires=control_wires, wires=target_wires, control_values=control_values)
def test_not_unique_wires(self): """Test that a ValueError is raised when work_wires is not complementary to control_wires""" control_wires = range(3) target_wire = 4 work_wires = range(2) with pytest.raises( ValueError, match="The work wires must be different from the control and target wires" ): qml.MultiControlledX( control_wires=control_wires, wires=target_wire, work_wires=work_wires )
def test_not_enough_workers(self): """Test that a ValueError is raised when more than 2 control wires are to be decomposed with no work wires supplied""" control_wires = range(3) target_wire = 4 op = qml.MultiControlledX(control_wires=control_wires, wires=target_wire) match = ( f"At least one work wire is required to decompose operation: {re.escape(op.__repr__())}" ) with pytest.raises(ValueError, match=match): op.decompose()
def op(op_name): ops_list = { "RX": qml.RX(0.123, wires=0), "RY": qml.RY(1.434, wires=0), "RZ": qml.RZ(2.774, wires=0), "S": qml.S(wires=0), "SX": qml.SX(wires=0), "T": qml.T(wires=0), "CNOT": qml.CNOT(wires=[0, 1]), "CZ": qml.CZ(wires=[0, 1]), "CY": qml.CY(wires=[0, 1]), "SWAP": qml.SWAP(wires=[0, 1]), "ISWAP": qml.ISWAP(wires=[0, 1]), "SISWAP": qml.SISWAP(wires=[0, 1]), "SQISW": qml.SQISW(wires=[0, 1]), "CSWAP": qml.CSWAP(wires=[0, 1, 2]), "PauliRot": qml.PauliRot(0.123, "Y", wires=0), "IsingXX": qml.IsingXX(0.123, wires=[0, 1]), "IsingXY": qml.IsingXY(0.123, wires=[0, 1]), "IsingYY": qml.IsingYY(0.123, wires=[0, 1]), "IsingZZ": qml.IsingZZ(0.123, wires=[0, 1]), "Identity": qml.Identity(wires=0), "Rot": qml.Rot(0.123, 0.456, 0.789, wires=0), "Toffoli": qml.Toffoli(wires=[0, 1, 2]), "PhaseShift": qml.PhaseShift(2.133, wires=0), "ControlledPhaseShift": qml.ControlledPhaseShift(1.777, wires=[0, 2]), "CPhase": qml.CPhase(1.777, wires=[0, 2]), "MultiRZ": qml.MultiRZ(0.112, wires=[1, 2, 3]), "CRX": qml.CRX(0.836, wires=[2, 3]), "CRY": qml.CRY(0.721, wires=[2, 3]), "CRZ": qml.CRZ(0.554, wires=[2, 3]), "Hadamard": qml.Hadamard(wires=0), "PauliX": qml.PauliX(wires=0), "PauliY": qml.PauliY(wires=0), "PauliZ": qml.PauliZ(wires=0), "CRot": qml.CRot(0.123, 0.456, 0.789, wires=[0, 1]), "DiagonalQubitUnitary": qml.DiagonalQubitUnitary(np.array([1.0, 1.0j]), wires=1), "ControlledQubitUnitary": qml.ControlledQubitUnitary( np.eye(2) * 1j, wires=[0], control_wires=[2] ), "MultiControlledX": qml.MultiControlledX(wires=(0, 1, 2), control_values="01"), "SingleExcitation": qml.SingleExcitation(0.123, wires=[0, 3]), "SingleExcitationPlus": qml.SingleExcitationPlus(0.123, wires=[0, 3]), "SingleExcitationMinus": qml.SingleExcitationMinus(0.123, wires=[0, 3]), "DoubleExcitation": qml.DoubleExcitation(0.123, wires=[0, 1, 2, 3]), "DoubleExcitationPlus": qml.DoubleExcitationPlus(0.123, wires=[0, 1, 2, 3]), "DoubleExcitationMinus": qml.DoubleExcitationMinus(0.123, wires=[0, 1, 2, 3]), "QFT": qml.QFT(wires=0), "QubitSum": qml.QubitSum(wires=[0, 1, 2]), "QubitCarry": qml.QubitCarry(wires=[0, 1, 2, 3]), "QubitUnitary": qml.QubitUnitary(np.eye(2) * 1j, wires=0), } return ops_list.get(op_name)
def test_MultiControlledX_control_values(self): """Test MultiControlledX special call with provided control values.""" with QuantumTape() as tape: qml.MultiControlledX(control_wires=[0, 1, 2, 3], wires=4, control_values="0101") _, ax = tape_mpl(tape) assert ax.patches[0].get_facecolor() == (1.0, 1.0, 1.0, 1.0) # white assert ax.patches[1].get_facecolor() == mpl.colors.to_rgba( plt.rcParams["lines.color"]) assert ax.patches[2].get_facecolor() == (1.0, 1.0, 1.0, 1.0) assert ax.patches[3].get_facecolor() == mpl.colors.to_rgba( plt.rcParams["lines.color"]) plt.close()
def test_MultiControlledX_no_control_values(self): """Test MultiControlledX gets a special call.""" with QuantumTape() as tape: qml.MultiControlledX(control_wires=[0, 1, 2, 3], wires=4) _, ax = tape_mpl(tape) layer = 0 assert len(ax.patches) == 5 for wire, patch in enumerate(ax.patches): assert patch.center == (layer, wire) # five wires, one control line, two target lines assert len(ax.lines) == 8 control_line = ax.lines[5] assert control_line.get_data() == ((layer, layer), (0, 4)) plt.close()
def parameterized_qubit_tape(): """A parametrized qubit ciruit.""" a, b, c = 0.1, 0.2, 0.3 angles = np.array([0.4, 0.5, 0.6]) with qml.tape.QuantumTape() as tape: qml.RX(a, wires=0) qml.RX(b, wires=1) qml.PauliZ(1) qml.CNOT(wires=[0, 1]).inv() qml.CRY(b, wires=[3, 1]) qml.RX(angles[0], wires=0) qml.RX(4 * angles[1], wires=1) qml.PhaseShift(17 / 9 * c, wires=2) qml.RZ(b, wires=3) qml.RX(angles[2], wires=2).inv() qml.CRY(0.3589, wires=[3, 1]).inv() qml.CSWAP(wires=[4, 2, 1]).inv() qml.QubitUnitary(np.eye(2), wires=[2]) qml.ControlledQubitUnitary(np.eye(2), control_wires=[0, 1], wires=[2]) qml.MultiControlledX(control_wires=[0, 1, 2], wires=[3]) qml.Toffoli(wires=[0, 2, 1]) qml.CNOT(wires=[0, 2]) qml.PauliZ(wires=[1]) qml.PauliZ(wires=[1]).inv() qml.CZ(wires=[0, 1]) qml.CZ(wires=[0, 2]).inv() qml.CY(wires=[1, 2]) qml.CY(wires=[2, 0]).inv() qml.CNOT(wires=[2, 1]) qml.CNOT(wires=[0, 2]) qml.SWAP(wires=[0, 2]).inv() qml.CNOT(wires=[1, 3]) qml.RZ(b, wires=3) qml.CSWAP(wires=[4, 0, 1]) qml.expval(qml.PauliY(0)), qml.var(qml.Hadamard(wires=1)), qml.sample(qml.PauliX(2)), qml.expval(qml.Hermitian(np.eye(4), wires=[3, 4])), return tape
def testcircuit(): qml.MultiControlledX(control_wires=[0, 2, 4, 5], wires=3)
(qml.PauliX(0), "X", "X"), (qml.PauliY(0), "Y", "Y"), (qml.PauliZ(0), "Z", "Z"), (qml.S(wires=0), "S", "S⁻¹"), (qml.T(wires=0), "T", "T⁻¹"), (qml.SX(wires=0), "SX", "SX⁻¹"), (qml.CNOT(wires=(0, 1)), "⊕", "⊕"), (qml.CZ(wires=(0, 1)), "Z", "Z"), (qml.CY(wires=(0, 1)), "Y", "Y"), (qml.SWAP(wires=(0, 1)), "SWAP", "SWAP⁻¹"), (qml.ISWAP(wires=(0, 1)), "ISWAP", "ISWAP⁻¹"), (qml.SISWAP(wires=(0, 1)), "SISWAP", "SISWAP⁻¹"), (qml.SQISW(wires=(0, 1)), "SISWAP", "SISWAP⁻¹"), (qml.CSWAP(wires=(0, 1, 2)), "SWAP", "SWAP"), (qml.Toffoli(wires=(0, 1, 2)), "⊕", "⊕"), (qml.MultiControlledX(control_wires=(0, 1, 2), wires=(3)), "⊕", "⊕"), (qml.Barrier(0), "||", "||"), (qml.WireCut(wires=0), "//", "//"), ] @pytest.mark.parametrize("op, label1, label2", label_data) def test_label_method(op, label1, label2): assert op.label() == label1 assert op.label(decimals=2) == label1 op.inv() assert op.label() == label2 control_data = [
"CRot": qml.CRot(0, 0, 0, wires=[0, 1]), "CSWAP": qml.CSWAP(wires=[0, 1, 2]), "CZ": qml.CZ(wires=[0, 1]), "CY": qml.CY(wires=[0, 1]), "DiagonalQubitUnitary": qml.DiagonalQubitUnitary(np.array([1, 1]), wires=[0]), "Hadamard": qml.Hadamard(wires=[0]), "MultiRZ": qml.MultiRZ(0, wires=[0]), "PauliX": qml.PauliX(wires=[0]), "PauliY": qml.PauliY(wires=[0]), "PauliZ": qml.PauliZ(wires=[0]), "PhaseShift": qml.PhaseShift(0, wires=[0]), "ControlledPhaseShift": qml.ControlledPhaseShift(0, wires=[0, 1]), "QubitStateVector": qml.QubitStateVector(np.array([1.0, 0.0]), wires=[0]), "QubitUnitary": qml.QubitUnitary(np.eye(2), wires=[0]), "ControlledQubitUnitary": qml.ControlledQubitUnitary(np.eye(2), control_wires=[1], wires=[0]), "MultiControlledX": qml.MultiControlledX(control_wires=[1, 2], wires=[0]), "RX": qml.RX(0, wires=[0]), "RY": qml.RY(0, wires=[0]), "RZ": qml.RZ(0, wires=[0]), "Rot": qml.Rot(0, 0, 0, wires=[0]), "S": qml.S(wires=[0]), "SWAP": qml.SWAP(wires=[0, 1]), "T": qml.T(wires=[0]), "SX": qml.SX(wires=[0]), "Toffoli": qml.Toffoli(wires=[0, 1, 2]), "QFT": qml.QFT(wires=[0, 1, 2]), "SingleExcitation": qml.SingleExcitation(0, wires=[0, 1]), "SingleExcitationPlus": qml.SingleExcitationPlus(0, wires=[0, 1]), "SingleExcitationMinus": qml.SingleExcitationMinus(0, wires=[0, 1]), "DoubleExcitation": qml.DoubleExcitation(0, wires=[0, 1, 2, 3]), "DoubleExcitationPlus": qml.DoubleExcitationPlus(0, wires=[0, 1, 2, 3]),
label_data = [ (qml.Hadamard(0), "H", "H"), (qml.PauliX(0), "X", "X"), (qml.PauliY(0), "Y", "Y"), (qml.PauliZ(0), "Z", "Z"), (qml.S(wires=0), "S", "S⁻¹"), (qml.T(wires=0), "T", "T⁻¹"), (qml.SX(wires=0), "SX", "SX⁻¹"), (qml.CNOT(wires=(0, 1)), "⊕", "⊕"), (qml.CZ(wires=(0, 1)), "Z", "Z"), (qml.CY(wires=(0, 1)), "Y", "Y"), (qml.SWAP(wires=(0, 1)), "SWAP", "SWAP⁻¹"), (qml.ISWAP(wires=(0, 1)), "ISWAP", "ISWAP⁻¹"), (qml.SISWAP(wires=(0, 1)), "SISWAP", "SISWAP⁻¹"), (qml.SQISW(wires=(0, 1)), "SISWAP", "SISWAP⁻¹"), (qml.CSWAP(wires=(0, 1, 2)), "SWAP", "SWAP"), (qml.Toffoli(wires=(0, 1, 2)), "⊕", "⊕"), (qml.MultiControlledX(control_wires=(0, 1, 2), wires=(3)), "⊕", "⊕"), ] @pytest.mark.parametrize("op, label1, label2", label_data) def test_label_method(op, label1, label2): assert op.label() == label1 assert op.label(decimals=2) == label1 op.inv() assert op.label() == label2