def qubit_props_from_props(properties: dict) -> list: """Returns a dictionary of `qiskit.providers.backend.QubitProperties` using a backend properties dictionary created by loading props.json payload. """ qubit_props = [] for qubit in properties["qubits"]: qubit_properties = {} for prop_dict in qubit: if prop_dict["name"] == "T1": qubit_properties["t1"] = apply_prefix(prop_dict["value"], prop_dict["unit"]) elif prop_dict["name"] == "T2": qubit_properties["t2"] = apply_prefix(prop_dict["value"], prop_dict["unit"]) elif prop_dict["name"] == "frequency": qubit_properties["frequency"] = apply_prefix( prop_dict["value"], prop_dict["unit"]) qubit_props.append(QubitProperties(**qubit_properties)) return qubit_props
def convert_durations_to_dt(qc: QuantumCircuit, dt_in_sec: float, inplace=True): """Convert all the durations in SI (seconds) into those in dt. Returns a new circuit if `inplace=False`. Parameters: qc (QuantumCircuit): Duration of dt in seconds used for conversion. dt_in_sec (float): Duration of dt in seconds used for conversion. inplace (bool): All durations are converted inplace or return new circuit. Returns: QuantumCircuit: Converted circuit if `inplace = False`, otherwise None. Raises: CircuitError: if fail to convert durations. """ if inplace: circ = qc else: circ = qc.copy() for instruction in circ.data: operation = instruction.operation if operation.unit == "dt" or operation.duration is None: continue if not operation.unit.endswith("s"): raise CircuitError(f"Invalid time unit: '{operation.unit}'") duration = operation.duration if operation.unit != "s": duration = apply_prefix(duration, operation.unit) operation.duration = duration_in_dt(duration, dt_in_sec) operation.unit = "dt" if circ.duration is not None: circ.duration = duration_in_dt(circ.duration, dt_in_sec) circ.unit = "dt" if not inplace: return circ else: return None
def _apply_prefix(self, value: float, unit: str) -> float: """ Given a SI unit prefix and value, apply the prefix to convert to standard SI unit. Args: value: The number to apply prefix to. unit: String prefix. Returns: Converted value. Raises: BackendPropertyError: If the units aren't recognized. """ try: return apply_prefix(value, unit) except Exception as ex: raise BackendPropertyError(f"Could not understand units: {unit}") from ex
def _thermal_relaxation_error( self, op: Instruction, qubits: Sequence[int] ): """Return thermal relaxation error on each operand qubit""" if not op.duration: if op.duration is None: warnings.warn("RelaxationNoisePass ignores instructions without duration," " you may need to schedule circuit in advance.", UserWarning) return None # Convert op duration to seconds if op.unit == 'dt': if self._dt is None: raise NoiseError( "RelaxationNoisePass cannot apply noise to a 'dt' unit duration" " without a dt time set.") duration = op.duration * self._dt else: duration = apply_prefix(op.duration, op.unit) t1s = self._t1s[qubits] t2s = self._t2s[qubits] p1s = self._p1s[qubits] # pylint: disable=invalid-name if op.num_qubits == 1: t1, t2, p1 = t1s[0], t2s[0], p1s[0] if t1 == np.inf and t2 == np.inf: return None return thermal_relaxation_error(t1, t2, duration, p1) # General multi-qubit case noise = QuantumCircuit(op.num_qubits) for qubit, (t1, t2, p1) in enumerate(zip(t1s, t2s, p1s)): if t1 == np.inf and t2 == np.inf: # No relaxation on this qubit continue error = thermal_relaxation_error(t1, t2, duration, p1) noise.append(error.to_instruction(), [qubit]) return noise
def _convert_unit(self, duration: float, from_unit: str, to_unit: str) -> Union[float, int]: if from_unit.endswith('s') and from_unit != 's': duration = apply_prefix(duration, from_unit) from_unit = 's' # assert both from_unit and to_unit in {'s', 'dt'} if from_unit == to_unit: return duration if self.dt is None: raise TranspilerError("dt is necessary to convert durations from '{}' to '{}'" .format(from_unit, to_unit)) if from_unit == 's' and to_unit == 'dt': return duration_in_dt(duration, self.dt) elif from_unit == 'dt' and to_unit == 's': return duration * self.dt else: raise TranspilerError("Conversion from '{}' to '{}' is not supported" .format(from_unit, to_unit))
def _convert_unit(self, duration: float, from_unit: str, to_unit: str) -> float: if from_unit.endswith("s") and from_unit != "s": duration = apply_prefix(duration, from_unit) from_unit = "s" # assert both from_unit and to_unit in {'s', 'dt'} if from_unit == to_unit: return duration if self.dt is None: raise TranspilerError( f"dt is necessary to convert durations from '{from_unit}' to '{to_unit}'" ) if from_unit == "s" and to_unit == "dt": if isinstance(duration, ParameterExpression): return duration / self.dt return duration_in_dt(duration, self.dt) elif from_unit == "dt" and to_unit == "s": return duration * self.dt else: raise TranspilerError(f"Conversion from '{from_unit}' to '{to_unit}' is not supported")
def convert_to_target(conf_dict: dict, props_dict: dict = None, defs_dict: dict = None) -> Target: """Uses configuration, properties and pulse defaults dicts to construct and return Target class. """ name_mapping = { "id": IGate(), "sx": SXGate(), "x": XGate(), "cx": CXGate(), "rz": RZGate(Parameter("λ")), "reset": Reset(), } custom_gates = {} qubit_props = None if props_dict: qubit_props = qubit_props_from_props(props_dict) target = Target(qubit_properties=qubit_props) # Parse from properties if it exsits if props_dict is not None: # Parse instructions gates = {} for gate in props_dict["gates"]: name = gate["gate"] if name in name_mapping: if name not in gates: gates[name] = {} elif name not in custom_gates: custom_gate = Gate(name, len(gate["qubits"]), []) custom_gates[name] = custom_gate gates[name] = {} qubits = tuple(gate["qubits"]) gate_props = {} for param in gate["parameters"]: if param["name"] == "gate_error": gate_props["error"] = param["value"] if param["name"] == "gate_length": gate_props["duration"] = apply_prefix( param["value"], param["unit"]) gates[name][qubits] = InstructionProperties(**gate_props) for gate, props in gates.items(): if gate in name_mapping: inst = name_mapping.get(gate) else: inst = custom_gates[gate] target.add_instruction(inst, props) # Create measurement instructions: measure_props = {} count = 0 for qubit in props_dict["qubits"]: qubit_prop = {} for prop in qubit: if prop["name"] == "readout_length": qubit_prop["duration"] = apply_prefix( prop["value"], prop["unit"]) if prop["name"] == "readout_error": qubit_prop["error"] = prop["value"] measure_props[(count, )] = InstructionProperties(**qubit_prop) count += 1 target.add_instruction(Measure(), measure_props) # Parse from configuration because properties doesn't exist else: for gate in conf_dict["gates"]: name = gate["name"] gate_props = {tuple(x): None for x in gate["coupling_map"]} if name in name_mapping: target.add_instruction(name_mapping[name], gate_props) else: custom_gate = Gate(name, len(gate["coupling_map"][0]), []) target.add_instruction(custom_gate, gate_props) measure_props = {(n, ): None for n in range(conf_dict["n_qubits"])} target.add_instruction(Measure(), measure_props) # parse global configuration properties dt = conf_dict.get("dt") if dt: target.dt = dt * 1e-9 if "timing_constraints" in conf_dict: target.granularity = conf_dict["timing_constraints"].get("granularity") target.min_length = conf_dict["timing_constraints"].get("min_length") target.pulse_alignment = conf_dict["timing_constraints"].get( "pulse_alignment") target.aquire_alignment = conf_dict["timing_constraints"].get( "acquire_alignment") # If pulse defaults exists use that as the source of truth if defs_dict is not None: # TODO remove the usage of PulseDefaults as it will be deprecated in the future pulse_defs = PulseDefaults.from_dict(defs_dict) inst_map = pulse_defs.instruction_schedule_map for inst in inst_map.instructions: for qarg in inst_map.qubits_with_instruction(inst): sched = inst_map.get(inst, qarg) if inst in target: try: qarg = tuple(qarg) except TypeError: qarg = (qarg, ) if inst == "measure": for qubit in qarg: target[inst][(qubit, )].calibration = sched else: target[inst][qarg].calibration = sched target.add_instruction(Delay(Parameter("t")), {(bit, ): None for bit in range(target.num_qubits)}) return target
def convert_to_target( configuration: BackendConfiguration, properties: BackendProperties = None, defaults: PulseDefaults = None, ) -> Target: """Uses configuration, properties and pulse defaults to construct and return Target class. """ name_mapping = { "id": IGate(), "sx": SXGate(), "x": XGate(), "cx": CXGate(), "rz": RZGate(Parameter("λ")), "reset": Reset(), } custom_gates = {} target = None # Parse from properties if it exsits if properties is not None: qubit_properties = qubit_props_list_from_props(properties=properties) target = Target( num_qubits=configuration.n_qubits, qubit_properties=qubit_properties ) # Parse instructions gates: Dict[str, Any] = {} for gate in properties.gates: name = gate.gate if name in name_mapping: if name not in gates: gates[name] = {} elif name not in custom_gates: custom_gate = Gate(name, len(gate.qubits), []) custom_gates[name] = custom_gate gates[name] = {} qubits = tuple(gate.qubits) gate_props = {} for param in gate.parameters: if param.name == "gate_error": gate_props["error"] = param.value if param.name == "gate_length": gate_props["duration"] = apply_prefix(param.value, param.unit) gates[name][qubits] = InstructionProperties(**gate_props) for gate, props in gates.items(): if gate in name_mapping: inst = name_mapping.get(gate) else: inst = custom_gates[gate] target.add_instruction(inst, props) # Create measurement instructions: measure_props = {} for qubit, _ in enumerate(properties.qubits): measure_props[(qubit,)] = InstructionProperties( duration=properties.readout_length(qubit), error=properties.readout_error(qubit), ) target.add_instruction(Measure(), measure_props) # Parse from configuration because properties doesn't exist else: target = Target(num_qubits=configuration.n_qubits) for gate in configuration.gates: name = gate.name gate_props = ( {tuple(x): None for x in gate.coupling_map} # type: ignore[misc] if hasattr(gate, "coupling_map") else {None: None} ) gate_len = len(gate.coupling_map[0]) if hasattr(gate, "coupling_map") else 0 if name in name_mapping: target.add_instruction(name_mapping[name], gate_props) else: custom_gate = Gate(name, gate_len, []) target.add_instruction(custom_gate, gate_props) target.add_instruction(Measure()) # parse global configuration properties if hasattr(configuration, "dt"): target.dt = configuration.dt if hasattr(configuration, "timing_constraints"): target.granularity = configuration.timing_constraints.get("granularity") target.min_length = configuration.timing_constraints.get("min_length") target.pulse_alignment = configuration.timing_constraints.get("pulse_alignment") target.aquire_alignment = configuration.timing_constraints.get( "acquire_alignment" ) # If a pulse defaults exists use that as the source of truth if defaults is not None: inst_map = defaults.instruction_schedule_map for inst in inst_map.instructions: for qarg in inst_map.qubits_with_instruction(inst): sched = inst_map.get(inst, qarg) if inst in target: try: qarg = tuple(qarg) except TypeError: qarg = (qarg,) if inst == "measure": for qubit in qarg: target[inst][(qubit,)].calibration = sched else: target[inst][qarg].calibration = sched if "delay" not in target: target.add_instruction( Delay(Parameter("t")), {(bit,): None for bit in range(target.num_qubits)} ) return target