def test_evaluate_qnode_default_input(self, get_circuit, output_dim, n_qubits): """Test if the _evaluate_qnode() method works correctly when the inputs argument is a default argument, i.e., that it gives the same result as calling the QNode directly""" c, w = get_circuit @qml.qnode(qml.device("default.qubit", wires=n_qubits), interface="torch") def c_default(w1, w2, w3, w4, w5, w6, w7, inputs=None): """Version of the circuit with inputs as a default argument""" qml.templates.AngleEmbedding(inputs, wires=list(range(n_qubits))) qml.templates.StronglyEntanglingLayers(w1, wires=list(range(n_qubits))) qml.RX(w2[0], wires=0) qml.RX(w3, wires=0) qml.Rot(*w4, wires=0) qml.templates.StronglyEntanglingLayers(w5, wires=list(range(n_qubits))) qml.Rot(*w6, wires=0) qml.RX(w7, wires=0) return [qml.expval(qml.PauliZ(i)) for i in range(output_dim)] layer = TorchLayer(c_default, w) x = torch.Tensor(np.ones(n_qubits)) layer_out = layer._evaluate_qnode(x).detach().numpy() weights = [layer.qnode_weights[weight].detach().numpy() for weight in ordered_weights] circuit_out = c(x, *weights) assert np.allclose(layer_out, circuit_out)
def test_evaluate_qnode_shuffled_args(self, get_circuit, output_dim, n_qubits): """Test if the _evaluate_qnode() method works correctly when the inputs argument is not the first positional argument, i.e., that it gives the same result as calling the QNode directly""" c, w = get_circuit @qml.qnode(qml.device("default.qubit", wires=n_qubits), interface="torch") def c_shuffled(w1, inputs, w2, w3, w4, w5, w6, w7): """Version of the circuit with a shuffled signature""" qml.templates.AngleEmbedding(inputs, wires=list(range(n_qubits))) qml.templates.StronglyEntanglingLayers(w1, wires=list(range(n_qubits))) qml.RX(w2[0], wires=0) qml.RX(w3, wires=0) qml.Rot(*w4, wires=0) qml.templates.StronglyEntanglingLayers(w5, wires=list(range(n_qubits))) qml.Rot(*w6, wires=0) qml.RX(w7, wires=0) return [qml.expval(qml.PauliZ(i)) for i in range(output_dim)] layer = TorchLayer(c_shuffled, w) x = torch.Tensor(np.ones(n_qubits)) layer_out = layer._evaluate_qnode(x) weights = layer.qnode_weights.values() circuit_out = c(x, *weights).type(x.dtype) assert torch.allclose(layer_out, circuit_out)
def test_var_keyword(self, n_qubits, output_dim): """Test that variable number of keyword arguments works""" dev = qml.device("default.qubit", wires=n_qubits) w = { "w1": (3, n_qubits, 3), "w2": (1,), "w3": 1, "w4": [3], "w5": (2, n_qubits, 3), "w6": 3, "w7": 0, } @qml.qnode(dev, interface="torch") def c(inputs, **kwargs): """A circuit that embeds data using the AngleEmbedding and then performs a variety of operations. The output is a PauliZ measurement on the first output_dim qubits. One set of parameters, w5, are specified as non-trainable.""" qml.templates.AngleEmbedding(inputs, wires=list(range(n_qubits))) qml.templates.StronglyEntanglingLayers(kwargs["w1"], wires=list(range(n_qubits))) qml.RX(kwargs["w2"][0], wires=0 % n_qubits) qml.RX(kwargs["w3"], wires=1 % n_qubits) qml.Rot(*kwargs["w4"], wires=2 % n_qubits) qml.templates.StronglyEntanglingLayers(kwargs["w5"], wires=list(range(n_qubits))) qml.Rot(*kwargs["w6"], wires=3 % n_qubits) qml.RX(kwargs["w7"], wires=4 % n_qubits) return [qml.expval(qml.PauliZ(i)) for i in range(output_dim)] layer = TorchLayer(c, w) x = torch.ones(n_qubits) layer_out = layer._evaluate_qnode(x) circuit_out = c(x, **layer.qnode_weights).type(x.dtype) assert torch.allclose(layer_out, circuit_out)
def test_evaluate_qnode(self, get_circuit, n_qubits): """Test if the _evaluate_qnode() method works correctly, i.e., that it gives the same result as calling the QNode directly""" c, w = get_circuit layer = TorchLayer(c, w) x = torch.ones(n_qubits) layer_out = layer._evaluate_qnode(x) weights = layer.qnode_weights.values() circuit_out = c(x, *weights).type(x.dtype) assert torch.allclose(layer_out, circuit_out)
def test_evaluate_qnode(self, get_circuit, n_qubits): """Test if the _evaluate_qnode() method works correctly, i.e., that it gives the same result as calling the QNode directly""" c, w = get_circuit layer = TorchLayer(c, w) x = torch.ones(n_qubits) layer_out = layer._evaluate_qnode(x).detach().numpy() weights = [layer.qnode_weights[weight].detach().numpy() for weight in ordered_weights] circuit_out = c(x, *weights) assert np.allclose(layer_out, circuit_out)
def test_non_input_defaults_tape_mode(self, n_qubits, output_dim): """Test that everything works when default arguments that are not the input argument are present in the QNode in tape mode""" if not qml.tape_mode_active(): pytest.skip("This functionality is only supported in tape mode.") dev = qml.device("default.qubit", wires=n_qubits) w = { "w1": (3, n_qubits, 3), "w2": (1, ), "w3": 1, "w4": [3], "w5": (2, n_qubits, 3), "w6": 3, "w7": 0, } @qml.qnode(dev, interface="torch") def c(inputs, w1, w2, w4, w5, w6, w7, w3=0.5): """A circuit that embeds data using the AngleEmbedding and then performs a variety of operations. The output is a PauliZ measurement on the first output_dim qubits. One set of parameters, w5, are specified as non-trainable.""" qml.templates.AngleEmbedding(inputs, wires=list(range(n_qubits))) qml.templates.StronglyEntanglingLayers(w1, wires=list(range(n_qubits))) qml.RX(w2[0], wires=0 % n_qubits) qml.RX(w3, wires=1 % n_qubits) qml.Rot(*w4, wires=2 % n_qubits) qml.templates.StronglyEntanglingLayers(w5, wires=list(range(n_qubits))) qml.Rot(*w6, wires=3 % n_qubits) qml.RX(w7, wires=4 % n_qubits) return [qml.expval(qml.PauliZ(i)) for i in range(output_dim)] layer = TorchLayer(c, w) x = torch.ones(n_qubits) layer_out = layer._evaluate_qnode(x) circuit_out = c(x, **layer.qnode_weights).type(x.dtype) assert torch.allclose(layer_out, circuit_out)