def from_tuplelist(tuple_list): """ Populates a Layout from a list containing virtual qubits---(QuantumRegister, int) tuples---, or None. Args: tuple_list (list): e.g.: [qr[0], None, qr[2], qr[3]] Returns: Layout: the corresponding Layout object Raises: LayoutError: If the elements are not (Register, integer) or None """ out = Layout() for physical, virtual in enumerate(tuple_list): if virtual is None: continue elif Layout.is_virtual(virtual): if virtual in out._v2p: raise LayoutError('Duplicate values not permitted; Layout is bijective.') out[virtual] = physical else: raise LayoutError("The list should contain elements of the form" " (Register, integer) or None") return out
def generate_from_intlist(int_list, *qregs): """Converts a list of integers to a Layout mapping virtual qubits (index of the list) to physical qubits (the list values). Args: int_list (list): A list of integers. *qregs (QuantumRegisters): The quantum registers to apply the layout to. Returns: Layout: The corresponding Layout object. Raises: LayoutError: Invalid input layout. """ # check for duplicate values in list if len(int_list) != len(set(int_list)): raise LayoutError( 'Duplicate values not permitted in integer layout.') n_qubits = sum(reg.size for reg in qregs) # Check if list is too short to cover all qubits if len(int_list) < n_qubits: err_msg = 'Integer list length must equal number of qubits in circuit.' raise LayoutError(err_msg) out = Layout() main_idx = 0 for qreg in qregs: for idx in range(qreg.size): out[(qreg, idx)] = int_list[main_idx] main_idx += 1 if main_idx != len(int_list): for int_item in int_list[main_idx:]: out[int_item] = None return out
def combine_into_edge_map(self, another_layout): """ Combines self and another_layout into an "edge map". For example:: self another_layout resulting edge map qr_1 -> 0 0 <- q_2 qr_1 -> q_2 qr_2 -> 2 2 <- q_1 qr_2 -> q_1 qr_3 -> 3 3 <- q_0 qr_3 -> q_0 The edge map is used to compose dags via, for example, compose_back. Args: another_layout (Layout): The other layout to combine. Returns: dict: A "edge map". Raises: LayoutError: another_layout can be bigger than self, but not smaller. Otherwise, raises. """ edge_map = dict() for virtual, physical in self.get_virtual_bits().items(): if physical not in another_layout._p2v: raise LayoutError( 'The wire_map_from_layouts() method does not support when the' ' other layout (another_layout) is smaller.') edge_map[virtual] = another_layout[physical] return edge_map
def __init__(self, input_dict=None): """construct a Layout from a bijective dictionary, mapping virtual qubits to physical qubits""" self._p2v = {} self._v2p = {} if input_dict is not None: if not isinstance(input_dict, dict): raise LayoutError("Layout constructor takes a dict") self.from_dict(input_dict)
def __delitem__(self, key): if isinstance(key, int): del self._p2v[key] del self._v2p[self._p2v[key]] elif isinstance(key, tuple) and \ len(key) == 2 and \ isinstance(key[0], Register) and isinstance(key[1], int): del self._v2p[key] del self._p2v[self._v2p[key]] else: raise LayoutError('The key to remove should be of the form' ' (Register, integer) or integer) and %s was provided' % (type(key),))
def order_based_on_type(value1, value2): """decides which one is physical/virtual based on the type. Returns (virtual, physical)""" if isinstance(value1, int) and Layout.is_virtual(value2): physical = value1 virtual = value2 elif isinstance(value2, int) and Layout.is_virtual(value1): physical = value2 virtual = value1 else: raise LayoutError('The map (%s -> %s) has to be a ((Register, integer) -> integer)' ' or the other way around.' % (type(value1), type(value2))) return virtual, physical
def _checktype(thing): """Checks if thing is a valid type""" if thing is None: return if isinstance(thing, int): return if isinstance(thing, tuple) and \ len(thing) == 2 and \ isinstance(thing[0], Register) and isinstance(thing[1], int): return raise LayoutError( 'The element %s should be a (Register, integer) tuple or an integer' % (thing, ))
def swap(self, left, right): """Swaps the map between left and right. Args: left (tuple or int): Item to swap with right. right (tuple or int): Item to swap with left. Raises: LayoutError: If left and right have not the same type. """ if type(left) is not type(right): raise LayoutError('The method swap only works with elements of the same type.') temp = self[left] self[left] = self[right] self[right] = temp
def __setitem__(self, key, value): Layout._checktype(key) Layout._checktype(value) if isinstance(key, type(value)): raise LayoutError( 'Key (%s) and value (%s) cannot have the same type' % (key, value)) if key in self: del self[key] if value in self: del self[value] if key is not None: dict.__setitem__(self, key, value) if value is not None: dict.__setitem__(self, value, key)
def set_length(self, amount_of_physical_bits): """ Extends the layout length to `amount_of_physical_bits`. Args: amount_of_physical_bits (int): The amount of physical_qubits to set in the layout. Raises: LayoutError: If amount_of_physical_bits is used to reduced the length instead of extending it. """ current_length = len(self) if amount_of_physical_bits < current_length: raise LayoutError( 'Lenght setting cannot be smaller than the current amount of physical' ' (qu)bits.') for new_physical_bit in range(current_length, amount_of_physical_bits): self[new_physical_bit] = None
def from_list(self, input_list): """ Populates a Layout from a list. Args: input_list (list): For example, [(QuantumRegister(3, 'qr'), 0), None, (QuantumRegister(3, 'qr'), 2), (QuantumRegister(3, 'qr'), 3)] Raises: LayoutError: If the elements are not (Register, integer) or None """ for physical, virtual in enumerate(input_list): if Layout.is_virtual(virtual): self._set_type_checked_item(virtual, physical) else: raise LayoutError( "The list should contain elements of the form" " (Register, integer) or None")