def test_mixed_inversion_with_nested_context(self): """Test that a sequence of operations is properly inverted when a nested context is present. Test that this also works for operations that were not queued.""" X0 = qml.PauliX(0) Z0 = qml.PauliZ(0) with pennylane.tape.OperationRecorder() as rec1: with pennylane.tape.OperationRecorder() as rec2: qml.Hadamard(wires=[0]) qml.CNOT(wires=[0, 1]) pu.inv([X0, qml.RX(1, wires=[0]), Z0, qml.RY(2, wires=[0])]) qml.CNOT(wires=[0, 1]) qml.Hadamard(wires=[0]) inv_queue = [ qml.Hadamard(wires=[0]), qml.CNOT(wires=[0, 1]), qml.RY(-2, wires=[0]), qml.PauliZ(0), qml.RX(-1, wires=[0]), qml.PauliX(0), qml.CNOT(wires=[0, 1]), qml.Hadamard(wires=[0]), ] for inv_op, exp_op in zip(rec1.queue, inv_queue): assert inv_op.name == exp_op.name assert inv_op.wires == exp_op.wires assert inv_op.data == exp_op.data for inv_op, exp_op in zip(rec2.queue, inv_queue): assert inv_op.name == exp_op.name assert inv_op.wires == exp_op.wires assert inv_op.data == exp_op.data
def test_inversion_with_context(self): """Test that a sequence of operations is properly inverted when a context is present.""" with pennylane._queuing.OperationRecorder() as rec: qml.Hadamard(wires=[0]) qml.CNOT(wires=[0, 1]) pu.inv([ qml.RX(1, wires=[0]), qml.RY(2, wires=[0]), qml.RZ(3, wires=[0]) ]) qml.CNOT(wires=[0, 1]) qml.Hadamard(wires=[0]) inv_queue = [ qml.Hadamard(wires=[0]), qml.CNOT(wires=[0, 1]), qml.RZ(3, wires=[0]).inv(), qml.RY(2, wires=[0]).inv(), qml.RX(1, wires=[0]).inv(), qml.CNOT(wires=[0, 1]), qml.Hadamard(wires=[0]), ] for inv_op, exp_op in zip(rec.queue, inv_queue): assert inv_op.name == exp_op.name assert inv_op.wires == exp_op.wires assert inv_op.data == exp_op.data
def test_non_queued_inversion_with_context(self): """Test that a sequence of operations is properly inverted when a context is present. Test that this also works for operations that were not queued.""" inv_ops = [ qml.RX(1, wires=[0]), qml.RY(2, wires=[0]), qml.RZ(3, wires=[0]) ] with pennylane.tape.OperationRecorder() as rec: qml.Hadamard(wires=[0]) qml.CNOT(wires=[0, 1]) pu.inv(inv_ops) qml.CNOT(wires=[0, 1]) qml.Hadamard(wires=[0]) inv_queue = [ qml.Hadamard(wires=[0]), qml.CNOT(wires=[0, 1]), qml.RZ(-3, wires=[0]), qml.RY(-2, wires=[0]), qml.RX(-1, wires=[0]), qml.CNOT(wires=[0, 1]), qml.Hadamard(wires=[0]), ] for inv_op, exp_op in zip(rec.queue, inv_queue): assert inv_op.name == exp_op.name assert inv_op.wires == exp_op.wires assert inv_op.data == exp_op.data
def test_non_operations_in_list(self, arg): """Test that the proper error is raised when the argument does not only contain operations.""" with pytest.raises( ValueError, match= "The given operation_list does not only contain Operations"): pu.inv(arg)
def test_argument_none_error(self): """Test that the proper error is raised when the argument type is wrong.""" with pytest.raises( ValueError, match="None was passed as an argument to inv. " + "This could happen if inversion of a template without the template decorator is attempted", ): pu.inv(None)
def qfunc(): qml.Hadamard(wires=[0]) qml.CNOT(wires=[0, 1]) pu.inv(dummy_template([0, 1])) qml.CNOT(wires=[0, 1]) qml.Hadamard(wires=[0]) return qml.expval(qml.PauliZ(0))
def qfunc(): qml.Hadamard(wires=[0]) qml.CNOT(wires=[0, 1]) pu.inv([X0, qml.RX(1, wires=[0]), Z0, qml.RY(2, wires=[0])]) qml.CNOT(wires=[0, 1]) qml.Hadamard(wires=[0]) return qml.expval(qml.PauliZ(0))
def qfunc(): qml.Hadamard(wires=[0]) qml.CNOT(wires=[0, 1]) pu.inv(inv_ops) qml.CNOT(wires=[0, 1]) qml.Hadamard(wires=[0]) return qml.expval(qml.PauliZ(0))
def test_template_double_inversion(self): """Test that inverting twice changes nothing for a template.""" inv_inv_ops = pu.inv(pu.inv(dummy_template([0, 1, 2]))).operations for inv_inv_op, exp_op in zip(inv_inv_ops, dummy_template([0, 1, 2])): assert inv_inv_op.name == exp_op.name assert inv_inv_op.wires == exp_op.wires assert inv_inv_op.data == exp_op.data
def test_callable_argument_error(self): """Test that the proper error is raised when the argument is a function.""" def func(x): return x with pytest.raises( ValueError, match="A function was passed as an argument to inv. ", ): pu.inv(func)
def test_double_inversion(self): """Test that inverting twice changes nothing.""" op_queue = [qml.PauliX(0), qml.PauliY(0), qml.PauliZ(0)] inv_inv_ops = pu.inv(pu.inv(op_queue)).operations for inv_inv_op, exp_op in zip(inv_inv_ops, op_queue): assert inv_inv_op.name == exp_op.name assert inv_inv_op.wires == exp_op.wires assert inv_inv_op.data == exp_op.data
def test_argument_wrapping(self): """Test that a single operation can be given to inv and is properly inverted.""" op = qml.RX(0.1, wires=0) exp_op = qml.RX(-0.1, wires=0) inv_ops = pu.inv(op).operations assert inv_ops[0].name == exp_op.name assert inv_ops[0].wires == exp_op.wires assert inv_ops[0].data == exp_op.data
def test_template_inversion_without_context(self): """Test that a template is properly inverted.""" inv_queue = inverted_dummy_template_operations([0, 1, 2]) inv_ops = pu.inv(dummy_template([0, 1, 2])).operations for inv_op, exp_op in zip(inv_ops, inv_queue): assert inv_op.name == exp_op.name assert inv_op.wires == exp_op.wires assert inv_op.data == exp_op.data
def test_argument_wrapping(self): """Test that a single operation can be given to inv and is properly inverted.""" op = qml.PauliX(0) exp_op = qml.PauliX(0).inv() inv_ops = pu.inv(op) assert inv_ops[0].name == exp_op.name assert inv_ops[0].wires == exp_op.wires assert inv_ops[0].params == exp_op.params
def test_inversion_without_context(self): """Test that a sequence of operations is properly inverted.""" op_queue = [qml.PauliX(0), qml.PauliY(0).inv(), qml.PauliZ(0)] inv_queue = [qml.PauliZ(0), qml.PauliY(0), qml.PauliX(0)] inv_ops = pu.inv(op_queue).operations for inv_op, exp_op in zip(inv_ops, inv_queue): assert inv_op.name == exp_op.name assert inv_op.wires == exp_op.wires assert inv_op.data == exp_op.data
def test_template_inversion_with_context(self): """Test that a template is properly inverted when a context is present.""" with pennylane.tape.OperationRecorder() as rec: qml.Hadamard(wires=[0]) qml.CNOT(wires=[0, 1]) pu.inv(dummy_template([0, 1, 2])) qml.CNOT(wires=[0, 1]) qml.Hadamard(wires=[0]) inv_queue = [ qml.Hadamard(wires=[0]), qml.CNOT(wires=[0, 1]), *inverted_dummy_template_operations([0, 1, 2]), qml.CNOT(wires=[0, 1]), qml.Hadamard(wires=[0]), ] for inv_op, exp_op in zip(rec.queue, inv_queue): assert inv_op.name == exp_op.name assert inv_op.wires == exp_op.wires assert inv_op.data == exp_op.data
def test_argument_type_error(self, arg): """Test that the proper error is raised when the argument type is wrong.""" with pytest.raises( ValueError, match="The provided operation_list is not iterable"): pu.inv(arg)