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
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
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
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.
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()
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)
# 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: