Example #1
0
def test_batch_execution_of_gradient(device, shots, mocker):
    """Test that the output of a parallelized execution of batch circuits to evaluate the
    gradient is correct in comparison to default.qubit."""
    qubits = 2
    layers = 2

    dev_aws = device(qubits)

    if isinstance(dev_aws, BraketLocalQubitDevice):
        pytest.skip(
            "Parallelized batch execution is only supported on the remote AWS device"
        )

    dev_aws._parallel = True

    dev_default = qml.device("default.qubit", wires=qubits)

    def func(weights):
        qml.templates.StronglyEntanglingLayers(weights, wires=range(qubits))
        return qml.expval(qml.PauliZ(0))

    qnode_aws = qml.QNode(func, dev_aws)
    qnode_default = qml.QNode(func, dev_default)

    shape = qml.templates.StronglyEntanglingLayers.shape(layers, qubits)
    weights = np.random.random(shape)

    dfunc_aws = qml.grad(qnode_aws)
    dfunc_default = qml.grad(qnode_default)

    spy1 = mocker.spy(BraketAwsQubitDevice, "execute")
    spy2 = mocker.spy(BraketAwsQubitDevice, "batch_execute")
    spy3 = mocker.spy(AwsDevice, "run_batch")

    res_aws = dfunc_aws(weights)
    res_default = dfunc_default(weights)

    if qml.version() >= "0.20.0":
        assert np.allclose(res_aws, res_default)
        spy1.assert_not_called()
        assert len(spy2.call_args_list) == 2
        assert len(spy3.call_args_list) == 2

        expected_circuits = qubits * layers * 3 * 2
        assert len(spy2.call_args_list[0][0]
                   [1]) == 1  # First batch_execute called for forward pass
        assert (len(spy2.call_args_list[1][0][1]) == expected_circuits
                )  # Then called for backward pass
    else:
        assert np.allclose(res_aws, res_default)
        spy1.assert_called_once()  # For a forward pass
        spy2.assert_called_once()
        spy3.assert_called_once()

        expected_circuits = qubits * layers * 3 * 2
        assert len(spy2.call_args_list[0][0][1]) == expected_circuits
Example #2
0
    def test_tracking(self, device, shots, tol):
        """Tests that a Device Tracker example correctly records resource usage"""

        # This test is run for both local and AWS managed simulators
        dev = device(1)

        @qml.qnode(dev, diff_method="parameter-shift")
        def circuit(x):
            qml.RX(x, wires=0)
            return qml.expval(qml.PauliZ(0))

        x = np.array(0.1, requires_grad=True)

        with qml.Tracker(circuit.device) as tracker:
            qml.grad(circuit)(x)

        expected_totals = {
            "executions": 3,
            "shots": 300,
            "batches": 2,
            "batch_len": 3
        }
        expected_history = {
            "executions": [1, 1, 1],
            "shots": [100, 100, 100],
            "batches": [1, 1],
            "batch_len": [1, 2],
        }

        # Breaking change in PL 0.20 affects how many batches are created from the gradient
        if qml.version() < "0.20":
            expected_totals["batches"] = 1
            expected_totals["batch_len"] = 2
            expected_history["batches"] = [1]
            expected_history["batch_len"] = [2]

        expected_latest = {"batches": 1, "batch_len": 2}

        for key, total in expected_totals.items():
            assert tracker.totals[key] == total
        for key, history in expected_history.items():
            assert tracker.history[key] == history
        assert tracker.latest == expected_latest

        assert len(tracker.history["braket_task_id"]) == 3

        if type(dev) == BraketAwsQubitDevice:
            durations = tracker.history["braket_simulator_ms"]
            billed_durations = tracker.history["braket_simulator_billed_ms"]
            assert len(durations) == 3
            assert len(billed_durations) == 3
            for duration, billed in zip(durations, billed_durations):
                assert (duration < MIN_SIMULATOR_BILLED_MS and billed
                        == MIN_SIMULATOR_BILLED_MS) or duration == billed
Example #3
0
def test_about(capfd):
    """
    about: Tests if the about string prints correct.
    """
    pennylane.about()
    out, err = capfd.readouterr()
    assert "Version:" in out
    pl_version_match = re.search(r"Version:\s+([\S]+)\n", out).group(1)
    assert pennylane.version().replace("-", ".") in pl_version_match
    assert "Numpy version" in out
    assert "Scipy version" in out
    assert "default.qubit" in out
    assert "default.gaussian" in out
Example #4
0
def test_about():
    """
    about: Tests if the about string prints correct.
    """
    f = io.StringIO()
    with contextlib.redirect_stdout(f):
        qml.about()
    out = f.getvalue().strip()

    assert "Version:" in out
    pl_version_match = re.search(r"Version:\s+([\S]+)\n", out).group(1)
    assert qml.version().replace("-", ".") in pl_version_match
    assert "Numpy version" in out
    assert "Scipy version" in out
    assert "default.qubit" in out
    assert "default.gaussian" in out
# Copyright 2018-2021 Xanadu Quantum Technologies Inc.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import argparse
import pennylane as qml
pl_version = '"' + qml.version() + '"'


def remove_quotes(my_str):
    """ A helper function to remove the quote chars (',")
    from the provided str.
    """
    clean_str = my_str.replace('"', '')  # remove "
    clean_str = clean_str.replace("'", "")  # remove '
    return clean_str


def bump_version(version_line, pre_release):
    """ A helper function which takes the current version string and
    replaces it with the bumped version depending on the pre/post
    release flag.
Example #6
0
def cli():
    """Parse the command line arguments, perform the requested action.
    """
    parser = argparse.ArgumentParser(description="PennyLane benchmarking tool")
    parser.add_argument("--noinfo",
                        action="store_true",
                        help="suppress information output")
    parser.add_argument("--version", action="version", version=__version__)
    parser.add_argument("-v",
                        "--verbose",
                        action="store_true",
                        help="verbose mode")
    parser.add_argument(
        "-d",
        "--device",
        type=lambda x: x.split(","),
        default="default.qubit",
        help=
        "comma-separated list of devices to run the benchmark on (default: %(default)s)",
    )
    parser.add_argument(
        "-q",
        "--qnode",
        type=lambda x: x.split(","),
        default="QNode",
        help=
        "comma-separated list of QNode subclasses to run the benchmark on (default: %(default)s)",
    )
    parser.add_argument(
        "-w",
        "--wires",
        type=int,
        default=3,
        help="number of wires to run the benchmark on (default: %(default)s)",
    )
    parser.add_argument("cmd",
                        choices=["time", "plot", "profile"],
                        help="function to perform")
    parser.add_argument("benchmark",
                        help="benchmark module name (without .py)")

    args = parser.parse_args()

    # look up information about the current HEAD Git commit
    res = subprocess.run(
        ["git", "log", "-1", "--pretty=%h %s"],
        stdout=subprocess.PIPE,
        encoding="utf-8",
        check=True,
    )
    title = res.stdout
    short_hash = title.split(" ", maxsplit=1)[0]

    print("Benchmarking PennyLane", qml.version())

    if args.verbose:
        print("Verbose mode on, results may not be representative.")

    if not args.noinfo:
        print("Commit:", col(title, "red"))
        qml.about()
        print()

    # import the requested benchmark module
    mod = importlib.import_module(args.benchmark)

    # execute the command
    if args.cmd == "plot":
        print("Performance plot: '{}' benchmark on {}, {}".format(
            mod.Benchmark.name, args.device, args.qnode))
        bms = [
            mod.Benchmark(qml.device(d, wires=args.wires),
                          qnode_type=q,
                          verbose=args.verbose) for d in args.device
            for q in args.qnode
        ]
        for k in bms:
            k.setup()
        plot(
            title,
            [k.benchmark for k in bms],
            [
                f"{args.benchmark} {k.device.short_name} {k.qnode_type}"
                for k in bms
            ],
            mod.Benchmark.n_vals,
        )
        for k in bms:
            k.teardown()
        return

    for d in args.device:
        for q in args.qnode:
            dev = qml.device(d, wires=args.wires)
            bm = mod.Benchmark(dev, qnode_type=q, verbose=args.verbose)
            bm.setup()
            text = col(f"'{bm.name}'", "blue") + " benchmark on " + col(
                f"{d}, {q}", "magenta")
            if args.cmd == "time":
                print("Timing:", text)
                timing(bm.benchmark)
            elif args.cmd == "profile":
                print("Profiling:", text)
                profile(bm.benchmark, identifier="_".join([short_hash, d, q]))
            else:
                raise ValueError("Unknown command.")
            bm.teardown()
Example #7
0
        outside a QNode."""
        self.logTestName()

        with self.assertRaisesRegex(QuantumFunctionError, 'can only be used inside a qfunc'):
            Identity(wires=0)

    def test_identiy_raises_exception_if_cannot_guess_device_type(self):
        """Tests that proper exceptions are raised if Identity fails to guess
        whether on a device is CV or qubit."""
        self.logTestName()

        dev = qml.device('default.qubit', wires=1)
        dev._expectation_map = {}

        @qml.qnode(dev)
        def circuit():
            return qml.expval.Identity(wires=0)

        with self.assertRaisesRegex(QuantumFunctionError, 'Unable to determine whether this device supports CV or qubit'):
            circuit()


if __name__ == '__main__':
    print('Testing PennyLane version ' + qml.version() + ', expval.')
    # run the tests in this file
    suite = unittest.TestSuite()
    for t in (TestExpval):
        ttt = unittest.TestLoader().loadTestsFromTestCase(t)
        suite.addTests(ttt)
    unittest.TextTestRunner().run(suite)
Example #8
0
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This module implements the logic required to automatically bump the version number in the version file and update the changelog accordingly."""
import argparse
import pennylane as qml

pl_version = '"' + qml.version(
) + '"'  # we expect PL v0.X.0 here if we're releasing v0.X+1.0 of the plugin


def bump_version(version_line, pre_release):
    """ A helper function which takes the current version string and
    replaces it with the bumped version depending on the pre/post
    release flag.

    Example:
        Assume that we have PennyLane version 0.18.0 as the latest release on PyPi.

        Pre-release:
        We gather the version number for the latest of PennyLane release (i.e., v0.18.0) and increment the middle value
        to obtain the version of the plugin that we'll release: v0.19.0.

        Post-release: