Beispiel #1
0
    def test_step_and_cost_with_grad_fn_grouped_input(self, tol):
        """Test that the correct cost and update is returned via the step_and_cost
        method for the QNG optimizer when providing an explicit grad_fn.
        Using a circuit with a single input containing all parameters."""
        dev = qml.device("default.qubit", wires=1)

        @qml.qnode(dev)
        def circuit(params):
            qml.RX(params[0], wires=0)
            qml.RY(params[1], wires=0)
            return qml.expval(qml.PauliZ(0))

        var = np.array([0.011, 0.012])
        opt = qml.QNGOptimizer(stepsize=0.01)

        # With autograd gradient function
        grad_fn = qml.grad(circuit)
        step1, cost1 = opt.step_and_cost(circuit, var, grad_fn=grad_fn)
        step2 = opt.step(circuit, var, grad_fn=grad_fn)

        # With more custom gradient function, forward has to be computed explicitly.
        grad_fn = lambda param: np.array(qml.grad(circuit)(param))
        step3, cost2 = opt.step_and_cost(circuit, var, grad_fn=grad_fn)
        step4 = opt.step(circuit, var, grad_fn=grad_fn)
        expected_step = var - opt.stepsize * 4 * grad_fn(var)
        expected_cost = circuit(var)

        for step in [step1, step2, step3, step3]:
            assert np.allclose(step, expected_step)
        assert np.isclose(cost1, expected_cost)
        assert np.isclose(cost2, expected_cost)
Beispiel #2
0
    def test_var_two_wires_with_parameters(self, qubit_device_2_wires, tol, name, input, expected_output, par):
        """Tests that variances are properly calculated for two-wire observables with parameters."""

        qubit_device_2_wires._state = np.array(input)
        res = qubit_device_2_wires.var(name, wires=[0, 1], par=par)

        assert np.isclose(res, expected_output, atol=tol, rtol=0)
Beispiel #3
0
    def test_four_term_case(self):
        """Tests the parameter shift rules for `CommutingEvolution` equal the
        finite difference result for a four term shift rule case."""

        n_wires = 2
        dev = qml.device("default.qubit", wires=n_wires)

        coeffs = [1, -1]
        obs = [qml.PauliX(0) @ qml.PauliY(1), qml.PauliY(0) @ qml.PauliX(1)]
        hamiltonian = qml.Hamiltonian(coeffs, obs)
        frequencies = (2, 4)

        @qml.qnode(dev)
        def circuit(time):
            qml.PauliX(0)
            qml.CommutingEvolution(hamiltonian, time, frequencies)
            return qml.expval(qml.PauliZ(0))

        x_vals = [
            np.array(x, requires_grad=True)
            for x in np.linspace(-np.pi, np.pi, num=10)
        ]

        grads_finite_diff = [
            qml.gradients.finite_diff(circuit)(x) for x in x_vals
        ]
        grads_param_shift = [
            qml.gradients.param_shift(circuit)(x) for x in x_vals
        ]

        assert all(np.isclose(grads_finite_diff, grads_param_shift, atol=1e-4))
Beispiel #4
0
    def test_two_term_case(self):
        """Tests the parameter shift rules for `CommutingEvolution` equal the
        finite difference result for a two term shift rule case."""

        n_wires = 1
        dev = qml.device("default.qubit", wires=n_wires)

        hamiltonian = qml.Hamiltonian([1], [qml.PauliX(0)])
        frequencies = (2, )

        @qml.qnode(dev)
        def circuit(time):
            qml.PauliX(0)
            qml.CommutingEvolution(hamiltonian, time, frequencies)
            return qml.expval(qml.PauliZ(0))

        x_vals = np.linspace(-np.pi, np.pi, num=10)

        grads_finite_diff = [
            qml.gradients.finite_diff(circuit)(x) for x in x_vals
        ]
        grads_param_shift = [
            qml.gradients.param_shift(circuit)(x) for x in x_vals
        ]

        assert all(np.isclose(grads_finite_diff, grads_param_shift, atol=1e-4))
Beispiel #5
0
def test_adjoint():
    """Tests the CommutingEvolution.adjoint method provides the correct adjoint operation."""

    n_wires = 2
    dev1 = qml.device("default.qubit", wires=n_wires)
    dev2 = qml.device("default.qubit", wires=n_wires)

    obs = [qml.PauliX(0) @ qml.PauliY(1), qml.PauliY(0) @ qml.PauliX(1)]
    coeffs = [1, -1]
    hamiltonian = qml.Hamiltonian(coeffs, obs)
    frequencies = (2, )

    @qml.qnode(dev1)
    def adjoint_evolution_circuit(time):
        for i in range(n_wires):
            qml.Hadamard(i)
        qml.adjoint(qml.CommutingEvolution)(hamiltonian, time, frequencies)
        return qml.expval(qml.PauliZ(1))

    @qml.qnode(dev2)
    def evolution_circuit(time):
        for i in range(n_wires):
            qml.Hadamard(i)
        qml.CommutingEvolution(hamiltonian, time, frequencies)
        return qml.expval(qml.PauliZ(1))

    evolution_circuit(0.13)
    adjoint_evolution_circuit(-0.13)

    assert all(np.isclose(dev1.state, dev2.state))
Beispiel #6
0
    def test_differentiable_hamiltonian(self):
        """Tests correct gradients are produced when the Hamiltonian is differentiable."""

        n_wires = 2
        dev = qml.device("default.qubit", wires=n_wires)
        obs = [qml.PauliX(0) @ qml.PauliY(1), qml.PauliY(0) @ qml.PauliX(1)]
        diff_coeffs = np.array([1.0, -1.0], requires_grad=True)
        frequencies = (2, 4)

        def parameterized_hamiltonian(coeffs):
            return qml.Hamiltonian(coeffs, obs)

        @qml.qnode(dev)
        def circuit(time, coeffs):
            qml.PauliX(0)
            qml.CommutingEvolution(parameterized_hamiltonian(coeffs), time,
                                   frequencies)
            return qml.expval(qml.PauliZ(0))

        x_vals = [
            np.array(x, requires_grad=True)
            for x in np.linspace(-np.pi, np.pi, num=10)
        ]

        grads_finite_diff = [
            np.hstack(qml.gradients.finite_diff(circuit)(x, diff_coeffs))
            for x in x_vals
        ]
        grads_param_shift = [
            np.hstack(qml.gradients.param_shift(circuit)(x, diff_coeffs))
            for x in x_vals
        ]

        assert np.isclose(grads_finite_diff, grads_param_shift,
                          atol=1e-6).all()
Beispiel #7
0
    def test_single_step(self, qnode, param, nums_frequency, spectra,
                         substep_optimizer, substep_kwargs):
        """Test executing a single step of the RotosolveOptimizer on a QNode."""
        param = tuple(np.array(p, requires_grad=True) for p in param)
        opt = RotosolveOptimizer(substep_optimizer, substep_kwargs)

        repack_param = len(param) == 1
        new_param_step = opt.step(
            qnode,
            *param,
            nums_frequency=nums_frequency,
            spectra=spectra,
        )
        if repack_param:
            new_param_step = (new_param_step, )

        assert (np.isscalar(new_param_step)
                and np.isscalar(param)) or len(new_param_step) == len(param)
        new_param_step_and_cost, old_cost = opt.step_and_cost(
            qnode,
            *param,
            nums_frequency=nums_frequency,
            spectra=spectra,
        )
        if repack_param:
            new_param_step_and_cost = (new_param_step_and_cost, )

        assert np.allclose(
            np.fromiter(_flatten(new_param_step_and_cost), dtype=float),
            np.fromiter(_flatten(new_param_step), dtype=float),
        )
        assert np.isclose(qnode(*param), old_cost)
Beispiel #8
0
    def test_full_output(self, fun, x_min, param, num_freq, optimizer, optimizer_kwargs):
        """Tests the ``full_output`` feature of Rotosolve, delivering intermediate cost
        function values at the univariate optimization substeps."""
        opt = RotosolveOptimizer()

        _, y_output_step = opt.step(
            fun,
            *param,
            num_freqs=num_freq,
            optimizer=optimizer,
            optimizer_kwargs=optimizer_kwargs,
            full_output=True,
        )
        new_param, old_cost, y_output_step_and_cost = opt.step_and_cost(
            fun,
            *param,
            num_freqs=num_freq,
            optimizer=optimizer,
            optimizer_kwargs=optimizer_kwargs,
            full_output=True,
        )
        # The following accounts for the unpacking functionality for length-1 param
        if len(param) == 1:
            new_param_step = (new_param,)
        expected_intermediate_x = successive_params(param, new_param)
        expected_y_output = [fun(*par) for par in expected_intermediate_x[1:]]

        assert np.allclose(y_output_step, expected_y_output)
        assert np.allclose(y_output_step_and_cost, expected_y_output)
        assert np.isclose(old_cost, fun(*expected_intermediate_x[0]))
Beispiel #9
0
    def test_single_step(self, qnode, param, num_freq, optimizer, optimizer_kwargs):
        opt = RotosolveOptimizer()

        repack_param = len(param) == 1
        new_param_step = opt.step(
            qnode,
            *param,
            num_freqs=num_freq,
            optimizer=optimizer,
            optimizer_kwargs=optimizer_kwargs,
        )
        if repack_param:
            new_param_step = (new_param_step,)

        assert (np.isscalar(new_param_step) and np.isscalar(param)) or len(new_param_step) == len(
            param
        )
        new_param_step_and_cost, old_cost = opt.step_and_cost(
            qnode,
            *param,
            num_freqs=num_freq,
            optimizer=optimizer,
            optimizer_kwargs=optimizer_kwargs,
        )
        if repack_param:
            new_param_step_and_cost = (new_param_step_and_cost,)

        assert np.allclose(
            np.fromiter(_flatten(new_param_step_and_cost), dtype=float),
            np.fromiter(_flatten(new_param_step), dtype=float),
        )
        assert np.isclose(qnode(*param), old_cost)
Beispiel #10
0
    def test_var_single_wire_with_parameters(self, qubit_device_1_wire, tol, name, input, expected_output, par):
        """Tests that expectation values are properly calculated for single-wire observables with parameters."""

        qubit_device_1_wire._state = np.array(input)
        res = qubit_device_1_wire.var(name, wires=[0], par=par)

        assert np.isclose(res, expected_output, atol=tol, rtol=0)
Beispiel #11
0
    def test_single_step_convergence(self, fun, x_min, param, nums_freq,
                                     exp_num_calls, substep_optimizer,
                                     substep_kwargs):
        """Tests convergence for easy classical functions in a single Rotosolve step.
        Includes testing of the parameter output shape and the old cost when using step_and_cost."""
        opt = RotosolveOptimizer(substep_optimizer, substep_kwargs)

        # Make only the first argument trainable
        param = (np.array(param[0], requires_grad=True), ) + param[1:]
        # Only one argument is marked as trainable -> All other arguments have to stay fixed
        new_param_step = opt.step(
            fun,
            *param,
            nums_frequency=nums_freq,
        )
        # The following accounts for the unpacking functionality for length-1 param
        if len(param) == 1:
            new_param_step = (new_param_step, )

        assert all(
            np.allclose(p, new_p)
            for p, new_p in zip(param[1:], new_param_step[1:]))

        # With trainable parameters, training should happen
        param = tuple(np.array(p, requires_grad=True) for p in param)
        new_param_step = opt.step(
            fun,
            *param,
            nums_frequency=nums_freq,
        )
        # The following accounts for the unpacking functionality for length-1 param
        if len(param) == 1:
            new_param_step = (new_param_step, )

        assert len(x_min) == len(new_param_step)
        assert np.allclose(
            np.fromiter(_flatten(x_min), dtype=float),
            np.fromiter(_flatten(new_param_step), dtype=float),
            atol=1e-5,
        )

        # Now with step_and_cost and trainable params
        new_param_step_and_cost, old_cost = opt.step_and_cost(
            fun,
            *param,
            nums_frequency=nums_freq,
        )
        # The following accounts for the unpacking functionality for length-1 param
        if len(param) == 1:
            new_param_step_and_cost = (new_param_step_and_cost, )

        assert len(x_min) == len(new_param_step_and_cost)
        assert np.allclose(
            np.fromiter(_flatten(new_param_step_and_cost), dtype=float),
            np.fromiter(_flatten(new_param_step), dtype=float),
            atol=1e-5,
        )
        assert np.isclose(old_cost, fun(*param))
Beispiel #12
0
    def test_qubit_identity(self, tensornet_device_1_wire, tol):
        """Test that the tensor network plugin provides correct result for the Identity expectation"""

        p = 0.543

        @qml.qnode(tensornet_device_1_wire)
        def circuit(x):
            """Test quantum function"""
            qml.RX(x, wires=0)
            return qml.expval(qml.Identity(0))

        assert np.isclose(circuit(p), 1, atol=tol, rtol=0)
Beispiel #13
0
    def test_supported_observable_two_wires_with_parameters(self, tensornet_device_2_wires, tol, name, state, expected_output, par):
        """Tests supported observables on two wires with parameters."""

        obs = getattr(qml.ops, name)

        assert tensornet_device_2_wires.supports_observable(name)

        @qml.qnode(tensornet_device_2_wires)
        def circuit():
            qml.QubitStateVector(np.array(state), wires=[0, 1])
            return qml.expval(obs(*par, wires=[0, 1]))

        assert np.isclose(circuit(), expected_output, atol=tol, rtol=0)
Beispiel #14
0
    def test_supported_observable_single_wire_no_parameters(self, tensornet_device_1_wire, tol, name, state, expected_output):
        """Tests supported observables on single wires without parameters."""

        obs = getattr(qml.ops, name)

        assert tensornet_device_1_wire.supports_observable(name)

        @qml.qnode(tensornet_device_1_wire)
        def circuit():
            qml.QubitStateVector(np.array(state), wires=[0])
            return qml.expval(obs(wires=[0]))

        assert np.isclose(circuit(), expected_output, atol=tol, rtol=0)
Beispiel #15
0
    def test_supported_gate_single_wire_with_parameters(self, tensornet_device_1_wire, tol, name, par, expected_output):
        """Tests supported gates that act on a single wire that are parameterized"""

        op = getattr(qml.ops, name)

        assert tensornet_device_1_wire.supports_operation(name)

        @qml.qnode(tensornet_device_1_wire)
        def circuit():
            op(*par, wires=0)
            return qml.expval(qml.PauliZ(0))

        assert np.isclose(circuit(), expected_output, atol=tol, rtol=0)
Beispiel #16
0
    def test_qubit_circuit(self, tensornet_device_1_wire, tol):
        """Test that the tensor network plugin provides correct result for a simple circuit"""

        p = 0.543

        @qml.qnode(tensornet_device_1_wire)
        def circuit(x):
            qml.RX(x, wires=0)
            return qml.expval(qml.PauliY(0))

        expected = -np.sin(p)

        assert np.isclose(circuit(p), expected, atol=tol, rtol=0)
    def test_random_layer_randomwires(self, n_subsystems):
        """Test that  random_layer() picks random wires."""
        n_rots = 500
        weights = np.random.randn(n_rots)

        with qml.utils.OperationRecorder() as rec:
            random_layer(weights=weights, wires=range(n_subsystems), ratio_imprim=0.3,
                         imprimitive=qml.CNOT, rotations=[RX, RY, RZ], seed=42)

        wires = [q._wires for q in rec.queue]
        wires_flat = [item for w in wires for item in w]
        mean_wire = np.mean(wires_flat)
        assert np.isclose(mean_wire, (n_subsystems - 1) / 2, atol=0.05)
    def test_random_layer_ratio_imprimitive(self, ratio):
        """Test that  random_layer() has the right ratio of imprimitive gates."""
        n_rots = 500
        n_wires = 2
        impr = CNOT
        weights = np.random.randn(n_rots)

        with qml.utils.OperationRecorder() as rec:
            random_layer(weights=weights, wires=range(n_wires), ratio_imprim=ratio,
                         imprimitive=CNOT, rotations=[RX, RY, RZ], seed=42)

        types = [type(q) for q in rec.queue]
        ratio_impr = types.count(impr) / len(types)
        assert np.isclose(ratio_impr, ratio, atol=0.05)
Beispiel #19
0
    def test_qubit_circuit(self, tol):
        """Test that the device provides the correct
        result for a simple circuit."""
        p = np.array(0.543)

        dev = qml.device("default.qubit.autograd", wires=1)

        @qml.qnode(dev, interface="autograd")
        def circuit(x):
            qml.RX(x, wires=0)
            return qml.expval(qml.PauliY(0))

        expected = -np.sin(p)

        assert circuit.diff_options["method"] == "backprop"
        assert np.isclose(circuit(p), expected, atol=tol, rtol=0)
Beispiel #20
0
    def simplify(self):
        r"""Simplifies the Hamiltonian by combining like-terms.

        **Example**

        >>> ops = [qml.PauliY(2), qml.PauliX(0) @ qml.Identity(1), qml.PauliX(0)]
        >>> H = qml.Hamiltonian([1, 1, -2], ops)
        >>> H.simplify()
        >>> print(H)
          (-1) [X0]
        + (1) [Y2]

        .. warning::

            Calling this method will reset ``grouping_indices`` to None, since
            the observables it refers to are updated.
        """
        data = []
        ops = []

        for i in range(len(self.ops)):  # pylint: disable=consider-using-enumerate
            op = self.ops[i]
            c = self.coeffs[i]
            op = op if isinstance(op, Tensor) else Tensor(op)

            ind = None
            for j, o in enumerate(ops):
                if op.compare(o):
                    ind = j
                    break

            if ind is not None:
                data[ind] += c
                if np.isclose(qml.math.toarray(data[ind]), np.array(0.0)):
                    del data[ind]
                    del ops[ind]
            else:
                ops.append(op.prune())
                data.append(c)

        self._coeffs = qml.math.stack(data) if data else []
        self.data = data
        self._ops = ops
        # reset grouping, since the indices refer to the old observables and coefficients
        self._grouping_indices = None
Beispiel #21
0
    def test_random_layer_randomwires(self, n_subsystems):
        """Test that  pennylane.templates.layers._random_layer() picks random wires."""
        np.random.seed(12)
        n_rots = 500
        dev = qml.device('default.qubit', wires=n_subsystems)
        weights = np.random.randn(n_rots)

        def circuit(weights):
            _random_layer(weights=weights, wires=range(n_subsystems))
            return qml.expval(qml.PauliZ(0))

        qnode = qml.QNode(circuit, dev)
        qnode(weights)
        queue = qnode.queue
        wires = [q._wires for q in queue]
        wires_flat = [item for w in wires for item in w]
        mean_wire = np.mean(wires_flat)
        assert np.isclose(mean_wire, (n_subsystems - 1) / 2, atol=0.05)
Beispiel #22
0
    def test_single_step_convergence(
        self, fun, x_min, param, num_freq, optimizer, optimizer_kwargs
    ):
        """Tests convergence for easy classical functions in a single Rotosolve step.
        Includes testing of the parameter output shape and the old cost when using step_and_cost."""
        opt = RotosolveOptimizer()

        new_param_step = opt.step(
            fun,
            *param,
            num_freqs=num_freq,
            optimizer=optimizer,
            optimizer_kwargs=optimizer_kwargs,
        )
        # The following accounts for the unpacking functionality for length-1 param
        if len(param) == 1:
            new_param_step = (new_param_step,)

        assert len(x_min) == len(new_param_step)
        assert np.allclose(
            np.fromiter(_flatten(x_min), dtype=float),
            np.fromiter(_flatten(new_param_step), dtype=float),
            atol=1e-5,
        )

        new_param_step_and_cost, old_cost = opt.step_and_cost(
            fun,
            *param,
            num_freqs=num_freq,
            optimizer=optimizer,
            optimizer_kwargs=optimizer_kwargs,
        )
        # The following accounts for the unpacking functionality for length-1 param
        if len(param) == 1:
            new_param_step_and_cost = (new_param_step_and_cost,)

        assert len(x_min) == len(new_param_step_and_cost)
        assert np.allclose(
            np.fromiter(_flatten(new_param_step_and_cost), dtype=float),
            np.fromiter(_flatten(new_param_step), dtype=float),
            atol=1e-5,
        )
        assert np.isclose(old_cost, fun(*param))
    def test_random_layer_imprimitive(self, ratio):
        """Test that  pennylane.templates.layers.RandomLayer() has the right ratio of imprimitive gates."""
        np.random.seed(12)
        n_rots = 500
        n_wires = 2
        impr = CNOT
        dev = qml.device('default.qubit', wires=n_wires)
        weights = np.random.randn(n_rots)

        def circuit(weights):
            RandomLayer(weights=weights, wires=range(n_wires), ratio_imprim=ratio, impr=CNOT)
            return qml.expval(qml.PauliZ(0))

        qnode = qml.QNode(circuit, dev)
        qnode(weights)
        queue = qnode.queue
        types = [type(q) for q in queue]
        ratio_impr = types.count(impr) / len(types)
        assert np.isclose(ratio_impr, ratio, atol=0.05)
Beispiel #24
0
    def test_nonzero_shots(self, tol):
        """Test that the default qubit plugin provides correct result for high shot number"""

        shots = 10 ** 5
        dev = qml.device("default.qubit", wires=1, shots=shots)

        p = 0.543

        @qml.qnode(dev)
        def circuit(x):
            """Test quantum function"""
            qml.RX(x, wires=0)
            return qml.expval(qml.PauliY(0))

        runs = []
        for _ in range(100):
            runs.append(circuit(p))

        assert np.isclose(np.mean(runs), -np.sin(p), atol=tol, rtol=0)
    def test_state_preparation_fidelity(self, tol, qubit_device_3_wires,
                                        state_vector, wires, target_state):
        """Tests that the template MottonenStatePreparation integrates correctly with PennyLane
        and produces states with correct fidelity."""
        @qml.qnode(qubit_device_3_wires)
        def circuit():
            MottonenStatePreparation(state_vector, wires)

            return qml.expval(qml.PauliZ(0)), qml.expval(
                qml.PauliZ(1)), qml.expval(qml.PauliZ(2))

        circuit()

        state = circuit.device.state.ravel()
        fidelity = abs(np.vdot(state, target_state))**2

        # We test for fidelity here, because the vector themselves will hardly match
        # due to imperfect state preparation
        assert np.isclose(fidelity, 1, atol=tol, rtol=0)
Beispiel #26
0
    def test_multi_qub_readout_correction(self):
        """Test the QPU plugin with readout errors and correction"""
        device = np.random.choice(TEST_QPU_LATTICES)
        dev_qpu = qml.device("forest.qpu",
                             device=device,
                             load_qc=False,
                             shots=10_000,
                             readout_error=[0.9, 0.75],
                             symmetrize_readout='exhaustive',
                             calibrate_readout='plus-eig',
                             parametric_compilation=False)

        @qml.qnode(dev_qpu)
        def circuit():
            qml.RY(np.pi / 2, wires=0)
            qml.RY(np.pi / 3, wires=1)
            return qml.expval(qml.PauliX(0) @ qml.PauliZ(1))

        result = circuit()

        assert np.isclose(result, 0.5, atol=3e-2)
Beispiel #27
0
    def test_single_step(self, fun, x_min, param, num_freq):
        """Tests convergence for easy classical functions in a single Rotosolve step
        with some arguments deactivated for training.
        Includes testing of the parameter output shape and the old cost when using step_and_cost."""
        substep_optimizer = "brute"
        substep_kwargs = None
        opt = RotosolveOptimizer(substep_optimizer, substep_kwargs)

        new_param_step = opt.step(
            fun,
            *param,
            nums_frequency=num_freq,
        )
        # The following accounts for the unpacking functionality for length-1 param
        if len(param) == 1:
            new_param_step = (new_param_step, )

        assert len(x_min) == len(new_param_step)
        assert np.allclose(
            np.fromiter(_flatten(x_min), dtype=float),
            np.fromiter(_flatten(new_param_step), dtype=float),
            atol=1e-5,
        )

        new_param_step_and_cost, old_cost = opt.step_and_cost(
            fun,
            *param,
            nums_frequency=num_freq,
        )
        # The following accounts for the unpacking functionality for length-1 param
        if len(param) == 1:
            new_param_step_and_cost = (new_param_step_and_cost, )

        assert len(x_min) == len(new_param_step_and_cost)
        assert np.allclose(
            np.fromiter(_flatten(new_param_step_and_cost), dtype=float),
            np.fromiter(_flatten(new_param_step), dtype=float),
            atol=1e-5,
        )
        assert np.isclose(old_cost, fun(*param))
    def test_random_layer_randomwires(self, n_subsystems):
        """Test that  _random_layer() picks random wires."""
        n_rots = 500
        dev = qml.device('default.qubit', wires=n_subsystems)
        weights = np.random.randn(n_rots)

        def circuit(weights):
            _random_layer(weights=weights,
                          wires=range(n_subsystems),
                          ratio_imprim=0.3,
                          imprimitive=qml.CNOT,
                          rotations=[RX, RY, RZ],
                          seed=42)
            return qml.expval(qml.PauliZ(0))

        qnode = qml.QNode(circuit, dev)
        qnode(weights)
        queue = qnode.queue
        wires = [q._wires for q in queue]
        wires_flat = [item for w in wires for item in w]
        mean_wire = np.mean(wires_flat)
        assert np.isclose(mean_wire, (n_subsystems - 1) / 2, atol=0.05)
Beispiel #29
0
    def test_multi_qub_no_readout_errors(self):
        """Test the QPU plugin with no readout errors or correction"""
        device = np.random.choice(TEST_QPU_LATTICES)
        dev_qpu = qml.device(
            "forest.qpu",
            device=device,
            load_qc=False,
            symmetrize_readout=None,
            calibrate_readout=None,
        )

        @qml.qnode(dev_qpu)
        def circuit():
            qml.RY(np.pi / 2, wires=0)
            qml.RY(np.pi / 3, wires=1)
            return qml.expval(qml.PauliX(0) @ qml.PauliZ(1))

        num_expts = 50
        result = 0.0
        for _ in range(num_expts):
            result += circuit()
        result /= num_expts

        assert np.isclose(result, 0.5, atol=2e-2)
Beispiel #30
0
    def __init__(
        self,
        ansatz,
        hamiltonian,
        device,
        interface="autograd",
        diff_method="best",
        optimize=False,
        **kwargs,
    ):
        if kwargs.get("measure", "expval") != "expval":
            raise ValueError(
                "ExpvalCost can only be used to construct sums of expectation values."
            )

        coeffs, observables = hamiltonian.terms

        self.hamiltonian = hamiltonian
        """Hamiltonian: the input Hamiltonian."""

        self.qnodes = None
        """QNodeCollection: The QNodes to be evaluated. Each QNode corresponds to the expectation
        value of each observable term after applying the circuit ansatz."""

        self._multiple_devices = isinstance(device, Sequence)
        """Bool: Records if multiple devices are input"""

        if np.isclose(qml.math.toarray(qml.math.count_nonzero(coeffs)), 0):
            self.cost_fn = lambda *args, **kwargs: np.array(0)
            return

        self._optimize = optimize

        self.qnodes = qml.map(ansatz,
                              observables,
                              device,
                              interface=interface,
                              diff_method=diff_method,
                              **kwargs)

        if self._optimize:

            if self._multiple_devices:
                raise ValueError(
                    "Using multiple devices is not supported when optimize=True"
                )

            obs_groupings, coeffs_groupings = qml.grouping.group_observables(
                observables, coeffs)
            d = device[0] if self._multiple_devices else device
            w = d.wires.tolist()

            @qml.qnode(device,
                       interface=interface,
                       diff_method=diff_method,
                       **kwargs)
            def circuit(*qnode_args, obs, **qnode_kwargs):
                """Converting ansatz into a full circuit including measurements"""
                ansatz(*qnode_args, wires=w, **qnode_kwargs)
                return [qml.expval(o) for o in obs]

            def cost_fn(*qnode_args, **qnode_kwargs):
                """Combine results from grouped QNode executions with grouped coefficients"""
                if device.shot_vector:
                    shots_batch = 0

                    for i in device.shot_vector:
                        shots_batch += i[1]

                    total = [0] * shots_batch

                    for o, c in zip(obs_groupings, coeffs_groupings):
                        res = circuit(*qnode_args, obs=o, **qnode_kwargs)

                        for i, batch_res in enumerate(res):
                            total[i] += sum(batch_res * c)
                else:
                    total = 0
                    for o, c in zip(obs_groupings, coeffs_groupings):
                        res = circuit(*qnode_args, obs=o, **qnode_kwargs)
                        total += sum([r * c_ for r, c_ in zip(res, c)])
                return total

            self.cost_fn = cost_fn

        else:
            self.cost_fn = qml.dot(coeffs, self.qnodes)