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))
Exemple #6
0
    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