Пример #1
0
def create_from_pure_vector(pure_vector,
                            state_type,
                            basis='pp',
                            evotype='default',
                            state_space=None,
                            on_construction_error='warn'):
    """ TODO: docstring -- create a State from a state vector """
    state_type_preferences = (state_type, ) if isinstance(state_type,
                                                          str) else state_type
    if state_space is None:
        state_space = _statespace.default_space_for_udim(len(pure_vector))

    for typ in state_type_preferences:
        try:
            if typ == 'computational':
                st = ComputationalBasisState.from_pure_vector(
                    pure_vector, basis, evotype, state_space)
            #elif typ == ('static stabilizer', 'static clifford'):
            #    st = StaticStabilizerState(...)  # TODO
            elif typ == 'static pure':
                st = StaticPureState(pure_vector, basis, evotype, state_space)
            elif typ == 'full pure':
                st = FullPureState(pure_vector, basis, evotype, state_space)
            elif typ in ('static', 'full', 'full TP', 'TrueCPTP'):
                superket = _bt.change_basis(_ot.state_to_dmvec(pure_vector),
                                            'std', basis)
                st = create_from_dmvec(superket, typ, basis, evotype,
                                       state_space)
            elif _ot.is_valid_lindblad_paramtype(typ):
                from ..operations import LindbladErrorgen as _LindbladErrorgen, ExpErrorgenOp as _ExpErrorgenOp
                static_state = create_from_pure_vector(
                    pure_vector, ('computational', 'static pure'), basis,
                    evotype, state_space)

                proj_basis = 'PP' if state_space.is_entirely_qubits else basis
                errorgen = _LindbladErrorgen.from_error_generator(
                    state_space.dim,
                    typ,
                    proj_basis,
                    basis,
                    truncate=True,
                    evotype=evotype,
                    state_space=state_space)
                st = ComposedState(static_state, _ExpErrorgenOp(errorgen))
            else:
                raise ValueError("Unknown state type '%s'!" % str(typ))

            return st  # if we get to here, then we've successfully created a state to return
        except (ValueError, AssertionError) as err:
            if on_construction_error == 'raise':
                raise err
            elif on_construction_error == 'warn':
                print(
                    'Failed to construct state with type "{}" with error: {}'.
                    format(typ, str(err)))
            pass  # move on to next type

    raise ValueError(
        "Could not create a state of type(s) %s from the given pure vector!" %
        (str(state_type)))
Пример #2
0
def create_from_dmvec(superket_vector,
                      state_type,
                      basis='pp',
                      evotype='default',
                      state_space=None):
    state_type_preferences = (state_type, ) if isinstance(state_type,
                                                          str) else state_type
    if state_space is None:
        state_space = _statespace.default_space_for_dim(len(superket_vector))

    for typ in state_type_preferences:
        try:
            if typ == "static":
                st = StaticState(superket_vector, evotype, state_space)
            elif typ == "full":
                st = FullState(superket_vector, evotype, state_space)
            elif typ == "full TP":
                st = TPState(superket_vector, basis, evotype, state_space)
            elif typ == "TrueCPTP":  # a non-lindbladian CPTP state that hasn't worked well...
                truncate = False
                st = CPTPState(superket_vector, basis, truncate, evotype,
                               state_space)

            elif _ot.is_valid_lindblad_paramtype(typ):
                from ..operations import LindbladErrorgen as _LindbladErrorgen, ExpErrorgenOp as _ExpErrorgenOp
                try:
                    dmvec = _bt.change_basis(superket_vector, basis, 'std')
                    purevec = _ot.dmvec_to_state(
                        dmvec
                    )  # raises error if dmvec does not correspond to a pure state
                    static_state = StaticPureState(purevec, basis, evotype,
                                                   state_space)
                except ValueError:
                    static_state = StaticState(superket_vector, evotype,
                                               state_space)

                proj_basis = 'PP' if state_space.is_entirely_qubits else basis
                errorgen = _LindbladErrorgen.from_error_generator(
                    state_space.dim,
                    typ,
                    proj_basis,
                    basis,
                    truncate=True,
                    evotype=evotype)
                return ComposedState(static_state, _ExpErrorgenOp(errorgen))

            else:
                # Anything else we try to convert to a pure vector and convert the pure state vector
                dmvec = _bt.change_basis(superket_vector, basis, 'std')
                purevec = _ot.dmvec_to_state(dmvec)
                st = create_from_pure_vector(purevec, typ, basis, evotype,
                                             state_space)
            return st
        except (ValueError, AssertionError):
            pass  # move on to next type

    raise ValueError(
        "Could not create a state of type(s) %s from the given superket vector!"
        % (str(state_type)))
Пример #3
0
def create_from_unitary_mx(unitary_mx, op_type, basis='pp', stdname=None, evotype='default', state_space=None):
    """ TODO: docstring - note that op_type can be a list/tuple of types in order of precedence """
    op_type_preferences = verbose_type_from_op_type(op_type)
    error_msgs = {}

    U = unitary_mx
    if state_space is None:
        state_space = _statespace.default_space_for_udim(U.shape[0])

    for typ in op_type_preferences:
        try:
            if typ == 'static standard' and stdname is not None:
                op = StaticStandardOp(stdname, basis, evotype, state_space)
            elif typ == 'static clifford':
                op = StaticCliffordOp(U, None, basis, evotype, state_space)
            elif typ == 'static unitary':
                op = StaticUnitaryOp(U, basis, evotype, state_space)
            elif typ == "full unitary":
                op = FullUnitaryOp(U, basis, evotype, state_space)
            elif typ in ('static', 'full', 'full TP', 'linear'):
                superop_mx = _ot.unitary_to_superop(U, basis)
                op = create_from_superop_mx(superop_mx, op_type, basis, stdname, evotype, state_space)
            elif _ot.is_valid_lindblad_paramtype(typ):  # maybe "lindblad XXX" where XXX is a valid lindblad type?
                if _np.allclose(U, _np.identity(U.shape[0], 'd')):
                    unitary_postfactor = None
                else:
                    unitary_postfactor = create_from_unitary_mx(
                        U, ('static standard', 'static clifford', 'static unitary'),
                        basis, stdname, evotype, state_space)

                proj_basis = 'PP' if state_space.is_entirely_qubits else basis
                errorgen = LindbladErrorgen.from_error_generator(state_space.dim, typ, proj_basis, basis,
                                                                 truncate=True, evotype=evotype,
                                                                 state_space=state_space)

                op = ExpErrorgenOp(errorgen) if (unitary_postfactor is None) \
                    else ComposedOp([unitary_postfactor, ExpErrorgenOp(errorgen)])

                if op.dim <= 16:  # only do this for up to 2Q operations, otherwise to_dense is too expensive
                    expected_superop_mx = _ot.unitary_to_superop(U, basis)
                    assert (_np.linalg.norm(op.to_dense('HilbertSchmidt') - expected_superop_mx) < 1e-6), \
                        "Failure to create Lindblad operation (maybe due the complex log's branch cut?)"
            else:
                raise ValueError("Unknown operation type '%s'!" % str(typ))

            return op  # if we get to here, then we've successfully created an op to return
        except (ValueError, AssertionError, AttributeError) as e:
            #_warnings.warn('Failed to create operator with type %s with error: %s' % (typ, e))
            error_msgs[typ] = str(e)  # # move on to text type

    raise ValueError("Could not create an operator of type(s) %s from the given unitary op:\n%s"
                     % (str(op_type), str(error_msgs)))
Пример #4
0
def povm_type_from_op_type(op_type):
    """Decode an op type into an appropriate povm type.

    Parameters:
    -----------
    op_type: str or list of str
        Operation parameterization type (or list of preferences)

    Returns
    -------
    povm_type_preferences: tuple of str
        POVM parameterization types
    """
    op_type_preferences = _mm.operations.verbose_type_from_op_type(op_type)

    # computational and TP are directly constructed as POVMS
    # All others pass through to the effects
    povm_conversion = {
        'auto': 'computational',
        'static standard': 'computational',
        'static clifford': 'computational',
        'static unitary': 'static pure',
        'full unitary': 'full pure',
        'static': 'static',
        'full': 'full',
        'full TP': 'full TP',
        'linear': 'full',
    }

    povm_type_preferences = []
    for typ in op_type_preferences:
        povm_type = None
        if _ot.is_valid_lindblad_paramtype(typ):
            # Lindblad types are passed through
            povm_type = typ
        else:
            povm_type = povm_conversion.get(typ, None)

        if povm_type is None:
            continue

        if povm_type not in povm_type_preferences:
            povm_type_preferences.append(povm_type)

    if len(povm_type_preferences) == 0:
        raise ValueError(
            'Could not convert any op types from {}.\n'.format(op_type_preferences)
            + '\tKnown op_types: Lindblad types or {}\n'.format(sorted(list(povm_conversion.keys())))
            + '\tValid povm_types: Lindblad types or {}'.format(sorted(list(set(povm_conversion.values()))))
        )

    return povm_type_preferences
Пример #5
0
def state_type_from_op_type(op_type):
    """Decode an op type into an appropriate state type.

    Parameters:
    -----------
    op_type: str or list of str
        Operation parameterization type (or list of preferences)

    Returns
    -------
    str
        State parameterization type
    """
    op_type_preferences = _mm.operations.verbose_type_from_op_type(op_type)

    state_conversion = {
        'auto': 'computational',
        'static standard': 'computational',
        'static clifford': 'computational',
        'static unitary': 'static pure',
        'full unitary': 'full pure',
        'static': 'static',
        'full': 'full',
        'full TP': 'full TP',
        'linear': 'full',
    }

    state_type_preferences = []
    for typ in op_type_preferences:
        state_type = None
        if _ot.is_valid_lindblad_paramtype(typ):
            # Lindblad types are passed through
            state_type = typ
        else:
            state_type = state_conversion.get(typ, None)

        if state_type is None:
            continue

        if state_type not in state_type_preferences:
            state_type_preferences.append(state_type)

    if len(state_type_preferences) == 0:
        raise ValueError('Could not convert any op types from {}.\n'.format(
            op_type_preferences) +
                         '\tKnown op_types: Lindblad types or {}\n'.format(
                             sorted(list(state_conversion.keys()))) +
                         '\tValid state_types: Lindblad types or {}'.format(
                             sorted(list(set(state_conversion.values())))))

    return state_type_preferences
Пример #6
0
def verbose_type_from_op_type(op_type):
    """Decode an op type into the "canonical", more verbose op type.

    Parameters:
    -----------
    op_type: str or list of str
        Operation parameterization type (or list of preferences)

    Returns
    -------
    povm_type_preferences: tuple of str
        POVM parameterization types
    """
    op_type_preferences = (op_type,) if isinstance(op_type, str) else op_type

    verbose_conversion = {
        'static standard': 'static standard',
        'static clifford': 'static clifford',
        'static unitary': 'static unitary',
        'full unitary': 'full unitary',
        'static': 'static',
        'full': 'full',
        'full TP': 'full TP',
        'TP': 'full TP',
        'linear': 'linear',
    }

    verbose_type_preferences = []
    for typ in op_type_preferences:
        verbose_type = None
        if _ot.is_valid_lindblad_paramtype(typ):
            # TODO: DO we want to prepend with lindblad?
            verbose_type = typ
        else:
            verbose_type = verbose_conversion.get(typ, None)

        if verbose_type is None:
            continue

        if verbose_type not in verbose_type_preferences:
            verbose_type_preferences.append(verbose_type)

    if len(verbose_type_preferences) == 0:
        raise ValueError(
            'Could not convert any op types from {}.\n'.format(op_type_preferences)
            + '\tKnown op_types: Lindblad types or {}\n'.format(sorted(list(verbose_conversion.keys())))
            + '\tValid povm_types: Lindblad types or {}'.format(sorted(list(set(verbose_conversion.values()))))
        )

    return tuple(verbose_type_preferences)
Пример #7
0
def instrument_type_from_op_type(op_type):
    """Decode an op type into an appropriate instrument type.

    Parameters:
    -----------
    op_type: str or list of str
        Operation parameterization type (or list of preferences)

    Returns
    -------
    instr_type_preferences: tuple of str
        POVM parameterization types
    """
    op_type_preferences = _mm.operations.verbose_type_from_op_type(op_type)

    # Limited set (only matching what is in convert)
    instr_conversion = {
        'auto': 'full',
        'static unitary': 'static unitary',
        'static clifford': 'static clifford',
        'static': 'static',
        'full': 'full',
        'full TP': 'full TP',
        'full unitary': 'full unitary',
    }

    instr_type_preferences = []
    for typ in op_type_preferences:
        instr_type = None
        if _ot.is_valid_lindblad_paramtype(typ):
            # Lindblad types are passed through as TP only (matching current convert logic)
            instr_type = "full TP"
        else:
            instr_type = instr_conversion.get(typ, None)

        if instr_type is None:
            continue

        if instr_type not in instr_type_preferences:
            instr_type_preferences.append(instr_type)

    if len(instr_type_preferences) == 0:
        raise ValueError('Could not convert any op types from {}.\n'.format(
            op_type_preferences) +
                         '\tKnown op_types: Lindblad types or {}\n'.format(
                             sorted(list(instr_conversion.keys()))) +
                         '\tValid instrument_types: Lindblad types or {}'.
                         format(sorted(list(set(instr_conversion.values())))))

    return instr_type_preferences
Пример #8
0
def create_from_superop_mx(superop_mx, op_type, basis='pp', stdname=None, evotype='default', state_space=None):
    op_type_preferences = (op_type,) if isinstance(op_type, str) else op_type
    error_msgs = {}

    for typ in op_type_preferences:
        try:
            if typ == "static":  # "static arbitrary"?
                op = StaticArbitraryOp(superop_mx, evotype, state_space)
            elif typ == "full":  # "full arbitrary"?
                op = FullArbitraryOp(superop_mx, evotype, state_space)
            elif typ in ["TP", "full TP"]:
                op = FullTPOp(superop_mx, evotype, state_space)
            elif typ == "linear":  # "linear arbitrary"?
                real = _np.isclose(_np.linalg.norm(superop_mx.imag), 0)
                op = LinearlyParamArbitraryOp(superop_mx, _np.array([]), {}, None, None, real, evotype, state_space)
            elif _ot.is_valid_lindblad_paramtype(typ):  # maybe "lindblad XXX" where XXX is a valid lindblad type?
                proj_basis = 'PP' if state_space.is_entirely_qubits else basis
                if _ot.superop_is_unitary(superop_mx, basis):
                    unitary_postfactor = StaticUnitaryOp(_ot.superop_to_unitary(superop_mx, basis, False),
                                                         basis, evotype, state_space)
                    errorgen = LindbladErrorgen.from_error_generator(state_space.dim, typ, proj_basis,
                                                                     basis, truncate=True, evotype=evotype,
                                                                     state_space=state_space)
                    ret = ComposedOp([unitary_postfactor, ExpErrorgenOp(errorgen)])
                else:
                    errorgen = LindbladErrorgen.from_operation_matrix(superop_mx, typ,
                                                                      proj_basis, mx_basis=basis, truncate=True,
                                                                      evotype=evotype, state_space=state_space)
                    ret = ExpErrorgenOp(errorgen)

                if ret.dim <= 16:  # only do this for up to 2Q operations, otherwise to_dense is too expensive
                    assert(_np.linalg.norm(superop_mx - ret.to_dense('HilbertSchmidt'))
                           < 1e-6), "Failure to create CPTP operation (maybe due the complex log's branch cut?)"
                return ret

            else:
                #Anything else we try to convert to a unitary and convert the unitary
                unitary_mx = _ot.superop_to_unitary(superop_mx, basis)  # raises ValueError if superop isn't unitary
                op = create_from_unitary_mx(unitary_mx, typ, basis, stdname, evotype, state_space)

            return op  # if we get to here, then we've successfully created an op to return
        except (ValueError, AssertionError) as e:
            error_msgs[typ] = str(e)  # # move on to text type

    raise ValueError("Could not create an operator of type(s) %s from the given superop:\n%s"
                     % (str(op_type), str(error_msgs)))
Пример #9
0
def create_from_pure_vectors(pure_vectors, povm_type, basis='pp', evotype='default', state_space=None,
                             on_construction_error='warn'):
    """ TODO: docstring -- create a POVM from a list/dict of (key, pure-vector) pairs """
    povm_type_preferences = (povm_type,) if isinstance(povm_type, str) else povm_type
    if not isinstance(pure_vectors, dict):  # then assume it's a list of (key, value) pairs
        pure_vectors = _collections.OrderedDict(pure_vectors)
    if state_space is None:
        state_space = _statespace.default_space_for_udim(len(next(iter(pure_vectors.values()))))

    for typ in povm_type_preferences:
        try:
            if typ == 'computational':
                povm = ComputationalBasisPOVM.from_pure_vectors(pure_vectors, evotype, state_space)
            #elif typ in ('static stabilizer', 'static clifford'):
            #    povm = ComputationalBasisPOVM(...evotype='stabilizer') ??
            elif typ in ('static pure', 'full pure', 'static', 'full'):
                effects = [(lbl, create_effect_from_pure_vector(vec, typ, basis, evotype, state_space))
                           for lbl, vec in pure_vectors.items()]
                povm = UnconstrainedPOVM(effects, evotype, state_space)
            elif typ == 'full TP':
                effects = [(lbl, create_effect_from_pure_vector(vec, "full", basis, evotype, state_space))
                           for lbl, vec in pure_vectors.items()]
                povm = TPPOVM(effects, evotype, state_space)
            elif _ot.is_valid_lindblad_paramtype(typ):
                from ..operations import LindbladErrorgen as _LindbladErrorgen, ExpErrorgenOp as _ExpErrorgenOp
                base_povm = create_from_pure_vectors(pure_vectors, ('computational', 'static pure'),
                                                     basis, evotype, state_space)

                proj_basis = 'PP' if state_space.is_entirely_qubits else basis
                errorgen = _LindbladErrorgen.from_error_generator(state_space.dim, typ, proj_basis, basis,
                                                                  truncate=True, evotype=evotype,
                                                                  state_space=state_space)
                povm = ComposedPOVM(_ExpErrorgenOp(errorgen), base_povm, mx_basis=basis)
            else:
                raise ValueError("Unknown POVM type '%s'!" % str(typ))

            return povm  # if we get to here, then we've successfully created a state to return
        except (ValueError, AssertionError) as err:
            if on_construction_error == 'raise':
                raise err
            elif on_construction_error == 'warn':
                print('Failed to construct povm with type "{}" with error: {}'.format(typ, str(err)))
            pass  # move on to next type

    raise ValueError("Could not create a POVM of type(s) %s from the given pure vectors!" % (str(povm_type)))
Пример #10
0
def create_from_dmvecs(superket_vectors, povm_type, basis='pp', evotype='default', state_space=None,
                       on_construction_error='warn'):
    """ TODO: docstring -- create a POVM from a list/dict of (key, pure-vector) pairs """
    povm_type_preferences = (povm_type,) if isinstance(povm_type, str) else povm_type
    if not isinstance(superket_vectors, dict):  # then assume it's a list of (key, value) pairs
        superket_vectors = _collections.OrderedDict(superket_vectors)

    for typ in povm_type_preferences:
        try:
            if typ in ("full", "static"):
                effects = [(lbl, create_effect_from_dmvec(dmvec, typ, basis, evotype, state_space))
                           for lbl, dmvec in superket_vectors.items()]
                povm = UnconstrainedPOVM(effects, evotype, state_space)
            elif typ == 'full TP':
                effects = [(lbl, create_effect_from_dmvec(dmvec, 'full', basis, evotype, state_space))
                           for lbl, dmvec in superket_vectors.items()]
                povm = TPPOVM(effects, evotype, state_space)
            elif _ot.is_valid_lindblad_paramtype(typ):
                from ..operations import LindbladErrorgen as _LindbladErrorgen, ExpErrorgenOp as _ExpErrorgenOp
                base_povm = create_from_dmvecs(superket_vectors, ('computational', 'static'),
                                               basis, evotype, state_space)

                proj_basis = 'PP' if state_space.is_entirely_qubits else basis
                errorgen = _LindbladErrorgen.from_error_generator(state_space.dim, typ, proj_basis, basis,
                                                                  truncate=True, evotype=evotype,
                                                                  state_space=state_space)
                povm = ComposedPOVM(_ExpErrorgenOp(errorgen), base_povm, mx_basis=basis)
            elif typ in ('computational', 'static pure', 'full pure'):
                # RESHAPE NOTE: .flatten() added to line below (to convert pure *col* vec -> 1D) to fix unit tests
                pure_vectors = {k: _ot.dmvec_to_state(_bt.change_basis(superket, basis, 'std')).flatten()
                                for k, superket in superket_vectors.items()}
                povm = create_from_pure_vectors(pure_vectors, typ, basis, evotype, state_space)
            else:
                raise ValueError("Unknown POVM type '%s'!" % str(typ))

            return povm  # if we get to here, then we've successfully created a state to return
        except (ValueError, AssertionError) as err:
            if on_construction_error == 'raise':
                raise err
            elif on_construction_error == 'warn':
                print('Failed to construct povm with type "{}" with error: {}'.format(typ, str(err)))
            pass  # move on to next type

    raise ValueError("Could not create a POVM of type(s) %s from the given pure vectors!" % (str(povm_type)))
Пример #11
0
def create_effect_from_dmvec(superket_vector, effect_type, basis='pp', evotype='default', state_space=None,
                             on_construction_error='warn'):
    effect_type_preferences = (effect_type,) if isinstance(effect_type, str) else effect_type
    if state_space is None:
        state_space = _statespace.default_space_for_dim(len(superket_vector))

    for typ in effect_type_preferences:
        try:
            if typ == "static":
                ef = StaticPOVMEffect(superket_vector, evotype, state_space)
            elif typ == "full":
                ef = FullPOVMEffect(superket_vector, evotype, state_space)
            elif _ot.is_valid_lindblad_paramtype(typ):
                from ..operations import LindbladErrorgen as _LindbladErrorgen, ExpErrorgenOp as _ExpErrorgenOp
                try:
                    dmvec = _bt.change_basis(superket_vector, basis, 'std')
                    purevec = _ot.dmvec_to_state(dmvec)  # raises error if dmvec does not correspond to a pure state
                    static_effect = StaticPOVMPureEffect(purevec, basis, evotype, state_space)
                except ValueError:
                    static_effect = StaticPOVMEffect(superket_vector, evotype, state_space)
                proj_basis = 'PP' if state_space.is_entirely_qubits else basis
                errorgen = _LindbladErrorgen.from_error_generator(state_space.dim, typ, proj_basis,
                                                                  basis, truncate=True, evotype=evotype)
                ef = ComposedPOVMEffect(static_effect, _ExpErrorgenOp(errorgen))
            else:
                # Anything else we try to convert to a pure vector and convert the pure state vector
                dmvec = _bt.change_basis(superket_vector, basis, 'std')
                purevec = _ot.dmvec_to_state(dmvec)  # raises error if dmvec does not correspond to a pure state

                ef = create_effect_from_pure_vector(purevec, typ, basis, evotype, state_space)
            return ef
        except (ValueError, AssertionError) as err:
            if on_construction_error == 'raise':
                raise err
            elif on_construction_error == 'warn':
                print('Failed to construct effect with type "{}" with error: {}'.format(typ, str(err)))
            pass  # move on to next type

    raise ValueError("Could not create an effect of type(s) %s from the given superket vector!" % (str(effect_type)))
Пример #12
0
def convert_errorgen(errorgen, to_type, basis, flatten_structure=False):
    """ TODO: docstring """
    to_types = verbose_type_from_op_type(to_type)
    error_msgs = {}

    for to_type in to_types:
        try:
            if not flatten_structure and isinstance(errorgen, (ComposedErrorgen, EmbeddedErrorgen)):
                def convert_errorgen_structure(eg):
                    if isinstance(eg, ComposedErrorgen):
                        return ComposedErrorgen([convert_errorgen_structure(f) for f in eg.factors],
                                                eg.evotype, eg.state_space)
                    elif isinstance(eg, EmbeddedErrorgen):
                        return EmbeddedErrorgen(eg.state_space, eg.target_labels,
                                                convert_errorgen_structure(eg.embedded_op))
                    else:
                        return convert_errorgen(eg)
                return convert_errorgen_structure(errorgen)

            elif isinstance(errorgen, LindbladErrorgen) and _ot.is_valid_lindblad_paramtype(to_type):
                # Convert the *parameterizations* of block only -- just use to_type as a lookup for
                # how to convert any blocks of each type (don't require all objects being converted have
                # all & exactly the Lindbald coefficient block types in `to_type`)
                to_type = LindbladParameterization.cast(to_type)
                block_param_conversion = {blk_type: param_mode for blk_type, param_mode
                                          in zip(to_type.block_types, to_type.param_modes)}
                converted_blocks = [blk.convert(block_param_conversion.get(blk._block_type, blk._param_mode))
                                    for blk in errorgen.coefficient_blocks]
                return LindbladErrorgen(converted_blocks, 'auto', errorgen.matrix_basis,
                                        errorgen.evotype, errorgen.state_space)
            else:
                raise ValueError("%s is not a valid error generator type!" % str(to_type))

        except Exception as e:
            error_msgs[to_type] = str(e)  # try next to_type

    raise ValueError("Could not convert error generator to type(s): %s\n%s" % (str(to_types), str(error_msgs)))
Пример #13
0
def convert(operation, to_type, basis, ideal_operation=None, flatten_structure=False):
    """
    Convert operation to a new type of parameterization.

    This potentially creates a new LinearOperator object, and
    Raises ValueError for invalid conversions.

    Parameters
    ----------
    operation : LinearOperator
        LinearOperator to convert

    to_type : {"full","full TP","static","static unitary","clifford",LINDBLAD}
        The type of parameterizaton to convert to.  "LINDBLAD" is a placeholder
        for the various Lindblad parameterization types.  See
        :method:`Model.set_all_parameterizations` for more details.

    basis : {'std', 'gm', 'pp', 'qt'} or Basis object
        The basis for `operation`.  Allowed values are Matrix-unit (std),
        Gell-Mann (gm), Pauli-product (pp), and Qutrit (qt)
        (or a custom basis object).

    ideal_operation : LinearOperator or "identity", optional
        The ideal (usually unitary) version of `operation`,
        potentially used when converting to an error-generator type.
        The special value `"identity"` can be used to indicate that the
        ideal operation is the identity.

    flatten_structure : bool, optional
        When `False`, the sub-members of composed and embedded operations
        are separately converted, leaving the original operation's structure
        unchanged.  When `True`, composed and embedded operations are "flattened"
        into a single operation of the requested `to_type`.

    Returns
    -------
    LinearOperator
        The converted operation, usually a distinct
        object from the operation object passed as input.
    """
    to_types = verbose_type_from_op_type(to_type)
    error_msgs = {}

    destination_types = {'full': FullArbitraryOp,
                         'full TP': FullTPOp,
                         'linear': LinearlyParamArbitraryOp,
                         'static': StaticArbitraryOp,
                         'static unitary': StaticUnitaryOp,
                         'static clifford': StaticCliffordOp}
    NoneType = type(None)

    for to_type in to_types:
        is_errorgen_type = _ot.is_valid_lindblad_paramtype(to_type)  # whether to_type specifies a type of errorgen
        try:
            if isinstance(operation, destination_types.get(to_type, NoneType)):
                return operation

            if not flatten_structure and isinstance(operation, (ComposedOp, EmbeddedOp)):
                def convert_structure(op):
                    if isinstance(op, ComposedOp):
                        return ComposedOp([convert_structure(f) for f in op.factorops], op.evotype, op.state_space)
                    elif isinstance(op, EmbeddedOp):
                        return EmbeddedOp(op.state_space, op.target_labels, convert_structure(op.embedded_op))
                    else:
                        return convert(op, to_type, basis, None, flatten_structure)
                return convert_structure(operation)

            elif isinstance(operation, ExpErrorgenOp) and is_errorgen_type:
                # Just an error generator type conversion
                return ExpErrorgenOp(convert_errorgen(operation.errorgen, to_type, basis, flatten_structure))

            elif (_ot.is_valid_lindblad_paramtype(to_type)
                  and (ideal_operation is not None or operation.num_params == 0)):  # e.g. TP -> Lindblad
                # Above: consider "isinstance(operation, StaticUnitaryOp)" instead of num_params == 0?
                #Convert a non-exp(errorgen) op to  exp(errorgen) * ideal
                proj_basis = 'PP' if operation.state_space.is_entirely_qubits else basis
                if ideal_operation == "identity":  # special value
                    postfactor_op = None
                    error_map_mx = operation.to_dense('HilbertSchmidt')  # error generators are only in HS space
                else:
                    postfactor_op = ideal_operation if (ideal_operation is not None) else operation
                    error_map_mx = _np.dot(operation.to_dense('HilbertSchmidt'),
                                           _np.linalg.inv(postfactor_op.to_dense('HilbertSchmidt')))

                errorgen = LindbladErrorgen.from_operation_matrix(error_map_mx, to_type,
                                                                  proj_basis, mx_basis=basis, truncate=True,
                                                                  evotype=operation.evotype,
                                                                  state_space=operation.state_space)
                ret = ComposedOp([postfactor_op.copy(), ExpErrorgenOp(errorgen)]) \
                    if (postfactor_op is not None) else ExpErrorgenOp(errorgen)

                if ret.dim <= 16:  # only do this for up to 2Q operations, otherwise to_dense is too expensive
                    assert(_np.linalg.norm(operation.to_dense('HilbertSchmidt') - ret.to_dense('HilbertSchmidt'))
                           < 1e-6), "Failure to create CPTP operation (maybe due the complex log's branch cut?)"
                return ret

            else:
                min_space = operation.evotype.minimal_space
                mx = operation.to_dense(min_space)
                if min_space == 'Hilbert':
                    return create_from_unitary_mx(mx, to_type, basis, None, operation.evotype, operation.state_space)
                else:
                    return create_from_superop_mx(mx, to_type, basis, None, operation.evotype, operation.state_space)

        except Exception as e:
            error_msgs[to_type] = str(e)  # try next to_type

    raise ValueError("Could not convert operation to to type(s): %s\n%s" % (str(to_types), str(error_msgs)))
Пример #14
0
def convert(state, to_type, basis, ideal_state=None, flatten_structure=False):
    """
    TODO: update docstring
    Convert SPAM vector to a new type of parameterization.

    This potentially creates a new State object.
    Raises ValueError for invalid conversions.

    Parameters
    ----------
    state : State
        State vector to convert

    to_type : {"full","full TP","static","static unitary","clifford",LINDBLAD}
        The type of parameterizaton to convert to.  "LINDBLAD" is a placeholder
        for the various Lindblad parameterization types.  See
        :method:`Model.set_all_parameterizations` for more details.

    basis : {'std', 'gm', 'pp', 'qt'} or Basis object
        The basis for `state`.  Allowed values are Matrix-unit (std),
        Gell-Mann (gm), Pauli-product (pp), and Qutrit (qt)
        (or a custom basis object).

    ideal_state : State, optional
        The ideal (usually pure) version of `state`,
        potentially used when converting to an error-generator type.

    flatten_structure : bool, optional
        When `False`, the sub-members of composed and embedded operations
        are separately converted, leaving the original state's structure
        unchanged.  When `True`, composed and embedded operations are "flattened"
        into a single state of the requested `to_type`.

    Returns
    -------
    State
        The converted State vector, usually a distinct
        object from the object passed as input.
    """
    to_types = to_type if isinstance(to_type, (tuple, list)) else (
        to_type, )  # HACK to support multiple to_type values
    error_msgs = {}

    destination_types = {
        'full': FullState,
        'full TP': TPState,
        'TrueCPTP': CPTPState,
        'static': StaticState,
        'static unitary': StaticPureState,
        'static clifford': ComputationalBasisState
    }
    NoneType = type(None)

    for to_type in to_types:
        try:
            if isinstance(state, destination_types.get(to_type, NoneType)):
                return state

            if not flatten_structure and isinstance(state, ComposedState):
                return ComposedState(
                    state.state_vec.copy(
                    ),  # don't convert (usually static) state vec
                    _mm.operations.convert(state.error_map, to_type, basis,
                                           "identity", flatten_structure))

            elif _ot.is_valid_lindblad_paramtype(to_type) and (
                    ideal_state is not None or state.num_params == 0):
                from ..operations import LindbladErrorgen as _LindbladErrorgen, ExpErrorgenOp as _ExpErrorgenOp
                st = ideal_state if (ideal_state is not None) else state
                proj_basis = 'PP' if state.state_space.is_entirely_qubits else basis
                errorgen = _LindbladErrorgen.from_error_generator(
                    state.state_space.dim,
                    to_type,
                    proj_basis,
                    basis,
                    truncate=True,
                    evotype=state.evotype)
                if st is not state and not _np.allclose(
                        st.to_dense(), state.to_dense()):
                    #Need to set errorgen so exp(errorgen)|st> == |state>
                    dense_st = st.to_dense()
                    dense_state = state.to_dense()

                    def _objfn(v):
                        errorgen.from_vector(v)
                        return _np.linalg.norm(
                            _spl.expm(errorgen.to_dense()) @ dense_st -
                            dense_state)

                    #def callback(x): print("callbk: ",_np.linalg.norm(x),_objfn(x))  # REMOVE
                    soln = _spo.minimize(_objfn,
                                         _np.zeros(errorgen.num_params, 'd'),
                                         method="CG",
                                         options={},
                                         tol=1e-8)  # , callback=callback)
                    #print("DEBUG: opt done: ",soln.success, soln.fun, soln.x)  # REMOVE
                    if not soln.success and soln.fun > 1e-6:  # not "or" because success is often not set correctly
                        raise ValueError(
                            "Failed to find an errorgen such that exp(errorgen)|ideal> = |state>"
                        )
                    errorgen.from_vector(soln.x)

                return ComposedState(st, _ExpErrorgenOp(errorgen))
            else:
                min_space = state.evotype.minimal_space
                vec = state.to_dense(min_space)
                if min_space == 'Hilbert':
                    return create_from_pure_vector(
                        vec,
                        to_type,
                        basis,
                        state.evotype,
                        state.state_space,
                        on_construction_error='raise')
                else:
                    return create_from_dmvec(vec, to_type, basis,
                                             state.evotype, state.state_space)

        except ValueError as e:
            #_warnings.warn('Failed to convert state to type %s with error: %s' % (to_type, e))
            error_msgs[to_type] = str(e)  # try next to_type

    raise ValueError("Could not convert state to to type(s): %s\n%s" %
                     (str(to_types), str(error_msgs)))
Пример #15
0
def convert_effect(effect, to_type, basis, ideal_effect=None, flatten_structure=False):
    """
    TODO: update docstring
    Convert POVM effect vector to a new type of parameterization.

    This potentially creates a new POVMEffect object.
    Raises ValueError for invalid conversions.

    Parameters
    ----------
    effect : POVMEffect
        POVM effect vector to convert

    to_type : {"full","TP","static","static pure","clifford",LINDBLAD}
        The type of parameterizaton to convert to.  "LINDBLAD" is a placeholder
        for the various Lindblad parameterization types.  See
        :method:`Model.set_all_parameterizations` for more details.

    basis : {'std', 'gm', 'pp', 'qt'} or Basis object
        The basis for `spamvec`.  Allowed values are Matrix-unit (std),
        Gell-Mann (gm), Pauli-product (pp), and Qutrit (qt)
        (or a custom basis object).

    extra : object, optional
        Additional information for conversion.

    Returns
    -------
    POVMEffect
        The converted POVM effect vector, usually a distinct
        object from the object passed as input.
    """
    to_types = to_type if isinstance(to_type, (tuple, list)) else (to_type,)  # HACK to support multiple to_type values
    destination_types = {'full': FullPOVMEffect,
                         'static': StaticPOVMEffect,
                         #'static pure': StaticPOVMPureEffect,
                         'static clifford': ComputationalBasisPOVMEffect}
    NoneType = type(None)

    for to_type in to_types:
        try:
            if isinstance(effect, destination_types.get(to_type, NoneType)):
                return effect

            if not flatten_structure and isinstance(effect, ComposedPOVMEffect):
                return ComposedPOVMEffect(effect.effect_vec.copy(),  # don't convert (usually static) effect vec
                                          _mm.operations.convert(effect.error_map, to_type, basis, "identity",
                                                                 flatten_structure))

            elif _ot.is_valid_lindblad_paramtype(to_type) and (ideal_effect is not None or effect.num_params == 0):
                from ..operations import LindbladErrorgen as _LindbladErrorgen, ExpErrorgenOp as _ExpErrorgenOp
                ef = ideal_effect if (ideal_effect is not None) else effect
                if ef is not effect and not _np.allclose(ef.to_dense(), effect.to_dense()):
                    raise NotImplementedError("Must supply ideal or a static effect to convert to a Lindblad type!")

                proj_basis = 'PP' if effect.state_space.is_entirely_qubits else basis
                errorgen = _LindbladErrorgen.from_error_generator(effect.state_space.dim, to_type, proj_basis,
                                                                  basis, truncate=True, evotype=effect.evotype)
                return ComposedPOVMEffect(ef, _ExpErrorgenOp(errorgen))

            else:
                min_space = effect.evotype.minimal_space
                vec = effect.to_dense(min_space)
                if min_space == 'Hilbert':
                    return create_effect_from_pure_vector(vec, to_type, basis, effect.evotype, effect.state_space,
                                                          on_construction_error='raise')
                else:
                    return create_effect_from_dmvec(vec, to_type, basis, effect.evotype, effect.state_space)
        except ValueError:
            pass

    raise ValueError("Could not convert effect to type(s): %s" % str(to_types))
Пример #16
0
def convert(povm, to_type, basis, ideal_povm=None, flatten_structure=False):
    """
    TODO: update docstring
    Convert a POVM to a new type of parameterization.

    This potentially creates a new object.  Raises ValueError for invalid conversions.

    Parameters
    ----------
    povm : POVM
        POVM to convert

    to_type : {"full","full TP","static","static pure","H+S terms",
        "H+S clifford terms","clifford"}
        The type of parameterizaton to convert to.  See
        :method:`Model.set_all_parameterizations` for more details.
        TODO docstring: update the options here.

    basis : {'std', 'gm', 'pp', 'qt'} or Basis object
        The basis for `povm`.  Allowed values are Matrix-unit (std),
        Gell-Mann (gm), Pauli-product (pp), and Qutrit (qt)
        (or a custom basis object).

    ideal_povm : POVM, optional
        The ideal version of `povm`, potentially used when
        converting to an error-generator type.

    flatten_structure : bool, optional
        When `False`, the sub-members of composed and embedded operations
        are separately converted, leaving the original POVM's structure
        unchanged.  When `True`, composed and embedded operations are "flattened"
        into a single POVM of the requested `to_type`.

    Returns
    -------
    POVM
        The converted POVM vector, usually a distinct
        object from the object passed as input.
    """
    to_types = to_type if isinstance(to_type, (tuple, list)) else (to_type,)  # HACK to support multiple to_type values
    error_msgs = {}

    destination_types = {'full TP': TPPOVM,
                         'static clifford': ComputationalBasisPOVM}
    NoneType = type(None)

    for to_type in to_types:
        try:
            if isinstance(povm, destination_types.get(to_type, NoneType)):
                return povm

            idl = dict(ideal_povm.items()) if ideal_povm is not None else {}  # ideal effects

            if to_type in ("full", "static", "static pure"):
                converted_effects = [(lbl, convert_effect(vec, to_type, basis, idl.get(lbl, None), flatten_structure))
                                     for lbl, vec in povm.items()]
                return UnconstrainedPOVM(converted_effects, povm.evotype, povm.state_space)

            elif to_type == "full TP":
                converted_effects = [(lbl, convert_effect(vec, "full", basis, idl.get(lbl, None), flatten_structure))
                                     for lbl, vec in povm.items()]
                return TPPOVM(converted_effects, povm.evotype, povm.state_space)

            elif _ot.is_valid_lindblad_paramtype(to_type):
                from ..operations import LindbladErrorgen as _LindbladErrorgen, ExpErrorgenOp as _ExpErrorgenOp

                #Construct a static "base" POVM
                if isinstance(povm, ComputationalBasisPOVM):  # special easy case
                    base_povm = ComputationalBasisPOVM(povm.state_space.num_qubits, povm.evotype)  # just copy it?
                else:
                    try:
                        if povm.evotype.minimal_space == 'Hilbert':
                            base_items = [(lbl, convert_effect(vec, 'static pure', basis,
                                                               idl.get(lbl, None), flatten_structure))
                                          for lbl, vec in povm.items()]
                        else:
                            raise RuntimeError('Evotype must be compatible with Hilbert ops to use pure effects')
                    except Exception:  # try static mixed states next:
                        base_items = [(lbl, convert_effect(vec, 'static', basis, idl.get(lbl, None), flatten_structure))
                                      for lbl, vec in povm.items()]
                    base_povm = UnconstrainedPOVM(base_items, povm.evotype, povm.state_space)

                proj_basis = 'PP' if povm.state_space.is_entirely_qubits else basis
                errorgen = _LindbladErrorgen.from_error_generator(povm.state_space.dim, to_type, proj_basis,
                                                                  basis, truncate=True, evotype=povm.evotype)
                return ComposedPOVM(_ExpErrorgenOp(errorgen), base_povm, mx_basis=basis)

            elif to_type == "static clifford":
                #Assume `povm` already represents state-vec ops, since otherwise we'd
                # need to change dimension
                nqubits = int(round(_np.log2(povm.dim)))

                #Check if `povm` happens to be a Z-basis POVM on `nqubits`
                v = (_np.array([1, 0], 'd'), _np.array([0, 1], 'd'))  # (v0,v1) - eigenstates of sigma_z
                for zvals, lbl in zip(_itertools.product(*([(0, 1)] * nqubits)), povm.keys()):
                    testvec = _functools.reduce(_np.kron, [v[i] for i in zvals])
                    if not _np.allclose(testvec, povm[lbl].to_dense()):
                        raise ValueError("Cannot convert POVM into a Z-basis stabilizer state POVM")

                #If no errors, then return a stabilizer POVM
                return ComputationalBasisPOVM(nqubits, 'stabilizer')

            else:
                raise ValueError("Invalid to_type argument: %s" % to_type)
        except Exception as e:
            error_msgs[to_type] = str(e)  # try next to_type

    raise ValueError("Could not convert POVM to to type(s): %s\n%s" % (str(to_types), str(error_msgs)))