Пример #1
0
    def old_approximate_quantum_error(error,
                                      *,
                                      operator_string=None,
                                      operator_dict=None,
                                      operator_list=None):
        if not isinstance(error, QuantumError):
            error = QuantumError(error)
        if error.number_of_qubits > 2:
            raise NoiseError(
                "Only 1-qubit and 2-qubit noises can be converted, {}-qubit "
                "noise found in model".format(error.number_of_qubits))

        error_kraus_operators = Kraus(error.to_quantumchannel()).data
        transformer = NoiseTransformer()
        if operator_string is not None:
            no_info_error = "No information about noise type {}".format(
                operator_string)
            operator_string = operator_string.lower()
            if operator_string not in transformer.named_operators.keys():
                raise RuntimeError(no_info_error)
            operator_lists = transformer.named_operators[operator_string]
            if len(operator_lists) < error.number_of_qubits:
                raise RuntimeError(
                    no_info_error +
                    " for {} qubits".format(error.number_of_qubits))
            operator_dict = operator_lists[error.number_of_qubits - 1]
        if operator_dict is not None:
            _, operator_list = zip(*operator_dict.items())
        if operator_list is not None:
            op_matrix_list = [
                transformer.operator_matrix(operator)
                for operator in operator_list
            ]
            probabilities = transformer.transform_by_operator_list(
                op_matrix_list, error_kraus_operators)
            identity_prob = numpy.round(1 - sum(probabilities), 9)
            if identity_prob < 0 or identity_prob > 1:
                raise RuntimeError(
                    "Channel probabilities sum to {}".format(1 -
                                                             identity_prob))
            quantum_error_spec = [([{
                'name': 'id',
                'qubits': [0]
            }], identity_prob)]
            op_circuit_list = [
                transformer.operator_circuit(operator)
                for operator in operator_list
            ]
            for (operator, probability) in zip(op_circuit_list, probabilities):
                quantum_error_spec.append((operator, probability))
            return QuantumError(quantum_error_spec)

        raise NoiseError(
            "Quantum error approximation failed - no approximating operators detected"
        )
Пример #2
0
def approximate_quantum_error(error,
                              *,
                              operator_string=None,
                              operator_dict=None,
                              operator_list=None):
    """Return an approximate QuantumError bases on the Hilbert-Schmidt metric.

    Currently this is only implemented for 1-qubit QuantumErrors.

    Args:
        error (QuantumError): the error to be approximated.
        operator_string (string or None): a name for a premade set of
            building blocks for the output channel (Default: None).
        operator_dict (dict or None): a dictionary whose values are the
            building blocks for the output channel (Default: None).
        operator_list (dict or None): list of building blocks for the
            output channel (Default: None).

    Returns:
        QuantumError: the approximate quantum error.

    Raises:
        NoiseError: if number of qubits is not supported or approximation
                    failsed.
        RuntimeError: If there's no information about the noise type

    Additional Information
    ----------------------
    The operator input precedence is as follows: list < dict < string
    if a string is given, dict is overwritten; if a dict is given, list is
    overwritten possible values for string are 'pauli', 'reset', 'clifford'
    For further information see `NoiseTransformer.named_operators`.
    """

    if not isinstance(error, QuantumError):
        error = QuantumError(error)
    if error.number_of_qubits > 1:
        raise NoiseError("Only 1-qubit noises can be converted, {}-qubit "
                         "noise found in model".format(error.number_of_qubits))

    error_kraus_operators = Kraus(error.to_quantumchannel()).data
    transformer = NoiseTransformer()
    if operator_string is not None:
        operator_string = operator_string.lower()
        if operator_string not in transformer.named_operators.keys():
            raise RuntimeError(
                "No information about noise type {}".format(operator_string))
        operator_dict = transformer.named_operators[operator_string]
    if operator_dict is not None:
        names, operator_list = zip(*operator_dict.items())
    if operator_list is not None:
        op_matrix_list = [
            transformer.operator_matrix(operator) for operator in operator_list
        ]
        probabilities = transformer.transform_by_operator_list(
            op_matrix_list, error_kraus_operators)
        identity_prob = 1 - sum(probabilities)
        if identity_prob < 0 or identity_prob > 1:
            raise RuntimeError(
                "Approximated channel operators probabilities sum to {}".
                format(1 - identity_prob))
        quantum_error_spec = [([{'name': 'id', 'qubits': [0]}], identity_prob)]
        op_circuit_list = [
            transformer.operator_circuit(operator)
            for operator in operator_list
        ]
        for (operator, probability) in zip(op_circuit_list, probabilities):
            quantum_error_spec.append((operator, probability))
        return QuantumError(quantum_error_spec)

    raise NoiseError(
        "Quantum error approximation failed - no approximating operators detected"
    )