Source code for qnetvo.cost.mermin_klyshko_inequality

import pennylane as qml
from pennylane import math
from ..qnodes import global_parity_expval_qnode


[docs]def mermin_klyshko_inputs_scalars(n): """Helper function for handling the algebra of combining correlator terms in the Mermin-Klyshko (MK) inequality. This function supports :meth:`mermin_klyshko_cost_fn`. :param n: The number of measurement nodes in the scenario. :type n: Int :returns: The first element of the returned tuple is a list of measurement inputs :math:`y_j\\in\\{0,1\\}` for the MK correlator terms. The second element of the returned tuple is a list of scalar multipliers for each correlator term. :rtype: Tuple(List[Int], List[Int]) """ inputs_list = [[0]] scalars_list = [1] for i in range(1, n): inputs_list_tmp = [] scalars_list_tmp = [] append_inputs = [0, 1, 0, 1] append_scalars = [1, 1, 1, -1] for i in range(len(inputs_list)): inputs = inputs_list[i] not_inputs = [(x + 1) % 2 for x in inputs] scalar = scalars_list[i] for i, append_input in enumerate(append_inputs): new_scalar_term = scalar * append_scalars[i] new_inputs = (inputs if i < 2 else not_inputs) + [append_input] if new_inputs in inputs_list_tmp: inputs_id = inputs_list_tmp.index(new_inputs) new_scalar = new_scalar_term + scalars_list_tmp[inputs_id] if new_scalar == 0: scalars_list_tmp.pop(inputs_id) inputs_list_tmp.pop(inputs_id) else: scalars_list_tmp[inputs_id] = new_scalar else: inputs_list_tmp.append(new_inputs) scalars_list_tmp.append(new_scalar_term) inputs_list = inputs_list_tmp scalars_list = scalars_list_tmp return inputs_list, scalars_list
[docs]def mermin_klyshko_cost_fn(ansatz, **qnode_kwargs): """Constructs an ansatz-specific cost function based upon the Mermin-Klyshko (MK) inequality. :param ansatz: The network ansatz for which to apply the MK inequality. :type ansatz: NetworkAnsatz :param qnode_kwargs: Keyword arguments passed through to the qnode constructors. :returns: A cost function, ``cost(*network_settings)``, that evaluates :math:`-I_{\\text{MK}}` for the supplied network settings. :rtype: Function """ mk_qnode = global_parity_expval_qnode(ansatz, **qnode_kwargs) num_meas_nodes = len(ansatz.layers[-1]) meas_inputs_list, scalars_list = mermin_klyshko_inputs_scalars(num_meas_nodes) static_prep_inputs = [[0] * len(layer_nodes) for layer_nodes in ansatz.layers[0:-1]] def cost(*network_settings): score = 0 num_correlators = len(meas_inputs_list) for i in range(num_correlators): meas_inputs = meas_inputs_list[i] scalar = scalars_list[i] settings = ansatz.qnode_settings(network_settings, static_prep_inputs + [meas_inputs]) score += scalar * mk_qnode(settings) return -(score) return cost
[docs]def mermin_klyshko_classical_bound(n): """The classical bound for the Mermin-Klyshko inequality is :math:`2^{n-1}`. :param n: The number of measurement nodes. :type n: Int :returns: The classical bound. :rtype: Float """ return 2 ** (n - 1)
[docs]def mermin_klyshko_quantum_bound(n): """The quantum bound for the Mermin-Klyshko inequality is :math:`2^{3(n-1)/2}`. :param n: The number of measurement nodes. :type n: Int :returns: The quantum bound. :rtype: Float """ return 2 ** (3 * (n - 1) / 2)