Example #1
0
 def test_or(self):
     """Test that logical or works."""
     crit_0 = qml.BooleanFn(lambda x: x < 4)
     crit_1 = qml.BooleanFn(lambda x: x > 9)
     crit = crit_0 | crit_1
     assert crit(-2)
     assert not crit(6)
     assert crit(10)
Example #2
0
 def test_and(self):
     """Test that logical conjunction works."""
     crit_0 = qml.BooleanFn(lambda x: x > 4)
     crit_1 = qml.BooleanFn(lambda x: x < 9)
     crit = crit_0 & crit_1
     assert not crit(-2)
     assert crit(6)
     assert not crit(10)
Example #3
0
def create_decomp_expand_fn(custom_decomps, dev, decomp_depth=10):
    """Creates a custom expansion function for a device that applies
    a set of specified custom decompositions.

    Args:
        custom_decomps (Dict[Union(str, qml.operation.Operation), Callable]): Custom
            decompositions to be applied by the device at runtime.
        dev (qml.Device): A quantum device.
        decomp_depth: The maximum depth of the expansion.

    Returns:
        Callable: A custom expansion function that a device can call to expand
        its tapes within a context manager that applies custom decompositions.

    **Example**

    Suppose we would like a custom expansion function that decomposes all CNOTs
    into CZs. We first define a decomposition function:

    .. code-block:: python

        def custom_cnot(wires):
            return [
                qml.Hadamard(wires=wires[1]),
                qml.CZ(wires=[wires[0], wires[1]]),
                qml.Hadamard(wires=wires[1])
            ]

    We then create the custom function (passing a device, in order to pick up any
    additional stopping criteria the expansion should have), and then register the
    result as a custom function of the device:

    >>> custom_decomps = {qml.CNOT : custom_cnot}
    >>> expand_fn = qml.transforms.create_decomp_expand_fn(custom_decomps, dev)
    >>> dev.custom_expand(expand_fn)
    """
    custom_op_names = [
        op if isinstance(op, str) else op.__name__
        for op in custom_decomps.keys()
    ]

    # Create a new expansion function; stop at things that do not have
    # custom decompositions, or that satisfy the regular device stopping criteria
    custom_fn = qml.transforms.create_expand_fn(
        decomp_depth,
        stop_at=qml.BooleanFn(lambda obj: obj.name not in custom_op_names),
        device=dev,
    )

    # Finally, we set the device's custom_expand_fn to a new one that
    # runs in a context where the decompositions have been replaced.
    def custom_decomp_expand(self, circuit, max_expansion=decomp_depth):
        with _custom_decomp_context(custom_decomps):
            return custom_fn(circuit, max_expansion=max_expansion)

    return custom_decomp_expand
Example #4
0
 def test_not(self):
     """Test that logical negation works."""
     crit = qml.BooleanFn(lambda x: x < 4)
     ncrit = ~crit
     assert crit(-2) and not ncrit(-2)
     assert not crit(10) and ncrit(10)
Example #5
0
 def test_basic_functionality(self, fn, arg, expected):
     """Test initialization and calling of BooleanFn."""
     crit = qml.BooleanFn(fn)
     assert crit(arg) == expected
Example #6
0
 def stopping_condition(self):
     """.BooleanFn: Returns the stopping condition for the device. The returned
     function accepts a queuable object (including a PennyLane operation
     and observable) and returns ``True`` if supported by the device."""
     return qml.BooleanFn(lambda obj: not isinstance(
         obj, qml.tape.QuantumTape) and self.supports_operation(obj.name))