def _hardware_aware_reset( mapping: ty.Dict[Qubit, int], circuit: QuantumCircuit, hardware: IBMQHardwareArchitecture, ) -> ty.Dict[Qubit, int]: starting_qubit = random.randint(0, hardware.qubit_number - 1) qubits: ty.List[int] = [starting_qubit] weights: ty.Dict[int, float] = dict() while len(qubits) < len(mapping): # 1. Update the weights for neighbour in hardware.neighbors(qubits[-1]): if neighbour not in qubits: if neighbour not in weights.keys(): weights[neighbour] = 0.5 * ( 1 - hardware.get_qubit_readout_error(neighbour)) else: weights[neighbour] += ( weights.get(neighbour, 0) + 1 - hardware.get_link_error_rate(qubits[-1], neighbour)) # Find the best weighted qubit best_weight, best_qubit = 0, None for qubit, weight in weights.items(): if weight > best_weight: best_qubit = qubit best_weight = weight # Insert it in the qubit list qubits.append(best_qubit) del weights[best_qubit] # Finally, return a mapping with the chosen qubits return {qubit: idx for qubit, idx in zip(mapping.keys(), qubits)}
def _hardware_aware_expand( mapping: ty.Dict[Qubit, int], circuit: QuantumCircuit, hardware: IBMQHardwareArchitecture, ) -> ty.Dict[Qubit, int]: qubits = list(mapping.values()) idle_qubits = {mapping[qubit] for qubit in _get_idle_qubits(circuit)} used_qubits = list(set(qubits) - idle_qubits) if not idle_qubits: return _random_shuffle(mapping, circuit, hardware) # Compute a weight for each qubit. # A qubit with a lot of links to other qubits in the mapping is good. # A qubit with bad links is not that good. weights: ty.List[float] = list() outside_qubits_weights = dict() for qubit in used_qubits: weights.append(0.5 * (1 - hardware.get_qubit_readout_error(qubit))) for neighbour in hardware.neighbors(qubit): # Only count the neighbour if it is also in the mapping. if neighbour in used_qubits: weights[-1] += 1 - hardware.get_link_error_rate( qubit, neighbour) # Else, we keep an eye on the qubits that are not in the mapping because # we will need the best of them to add it to the mapping. else: if neighbour not in outside_qubits_weights.keys(): outside_qubits_weights[neighbour] = 0.5 * ( 1 - hardware.get_qubit_readout_error(qubit)) else: outside_qubits_weights[neighbour] += ( outside_qubits_weights.get(neighbour, 0) + 1 - hardware.get_link_error_rate(qubit, neighbour)) worst_qubit_index = _argmin(weights) best_outside_qubit_index = None best_outside_weight = 0 for neighbour, weight in outside_qubits_weights.items(): if weight > best_outside_weight: best_outside_qubit_index = neighbour best_outside_weight = weight # Now exchange the 2 qubits inverse_mapping = {v: k for k, v in mapping.items()} inverse_mapping[worst_qubit_index], inverse_mapping[ best_outside_qubit_index] = ( inverse_mapping[best_outside_qubit_index], inverse_mapping[worst_qubit_index], ) return {v: k for k, v in inverse_mapping.items()}
def _get_swap_error_cost(node, hardware: IBMQHardwareArchitecture) -> float: source, sink = node cnot_fidelity = 1 - hardware.get_link_error_rate(source, sink) reversed_cnot_fidelity = 1 - hardware.get_link_error_rate(sink, source) return 1 - cnot_fidelity * reversed_cnot_fidelity * max( cnot_fidelity, reversed_cnot_fidelity)