Source code for qiskit.aqua.utils.entangler_map

# -*- coding: utf-8 -*-

# This code is part of Qiskit.
#
# (C) Copyright IBM 2018, 2019.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""
This module contains the definition of creating and validating entangler map
based on the number of qubits.
"""


[docs]def get_entangler_map(map_type, num_qubits, offset=0): """Utility method to get an entangler map among qubits. Args: map_type (str): 'full' entangles each qubit with all the subsequent ones 'linear' entangles each qubit with the next 'sca' (shifted circular alternating entanglement) is a circular entanglement where the 'long' entanglement is shifted by one position every block and every block the role or control/target qubits alternate num_qubits (int): Number of qubits for which the map is needed offset (int): Some map_types (e.g. 'sca') can shift the gates in the entangler map by the specified integer offset. Returns: list: A map of qubit index to an array of indexes to which this should be entangled Raises: ValueError: if map_type is not valid. """ ret = [] if num_qubits > 1: if map_type == 'full': ret = [[i, j] for i in range(num_qubits) for j in range(i + 1, num_qubits)] elif map_type == 'linear': ret = [[i, i + 1] for i in range(num_qubits - 1)] elif map_type == 'sca': offset_idx = offset % num_qubits if offset_idx % 2 == 0: # even block numbers for i in reversed(range(offset_idx)): ret += [[i, i + 1]] ret += [[num_qubits - 1, 0]] for i in reversed(range(offset_idx + 1, num_qubits)): ret += [[i - 1, i]] else: # odd block numbers for i in range(num_qubits - offset_idx - 1, num_qubits - 1): ret += [[i + 1, i]] ret += [[0, num_qubits - 1]] for i in range(num_qubits - offset_idx - 1): ret += [[i + 1, i]] else: raise ValueError("map_type only supports 'full', 'linear' or 'sca' type.") return ret
[docs]def validate_entangler_map(entangler_map, num_qubits, allow_double_entanglement=False): """Validate a user supplied entangler map and converts entries to ints. Args: entangler_map (list[list]) : An entangler map, keys are source qubit index (int), value is array of target qubit index(es) (int) num_qubits (int) : Number of qubits allow_double_entanglement (bool): If we allow in two qubits can be entangled each other Returns: list: Validated/converted map Raises: TypeError: entangler map is not list type or list of list ValueError: the index of entangler map is out of range ValueError: the qubits are cross-entangled. """ if isinstance(entangler_map, dict): raise TypeError("The type of entangler map is changed to list of list.") if not isinstance(entangler_map, list): raise TypeError("Entangler map type 'list' expected") for src_to_targ in entangler_map: if not isinstance(src_to_targ, list): raise TypeError('Entangle index list expected but got {}'.format(type(src_to_targ))) ret_map = [] ret_map = [[int(src), int(targ)] for src, targ in entangler_map] for src, targ in ret_map: if src < 0 or src >= num_qubits: raise ValueError( 'Qubit entangle source value {} invalid for {} qubits'.format(src, num_qubits)) if targ < 0 or targ >= num_qubits: raise ValueError( 'Qubit entangle target value {} invalid for {} qubits'.format(targ, num_qubits)) if not allow_double_entanglement and [targ, src] in ret_map: raise ValueError('Qubit {} and {} cross-entangled.'.format(src, targ)) return ret_map