示例#1
0
def chain_break_frequency(samples_like, embedding):
    """Determine the frequency of chain breaks in the given samples.

    Args:
        samples_like (samples_like/:obj:`dimod.SampleSet`):
            A collection of raw samples. 'samples_like' is an extension of NumPy's array_like.
            See :func:`dimod.as_samples`.

        embedding (dict):
            Mapping from source graph to target graph as a dict of form {s: {t, ...}, ...},
            where s is a source-model variable and t is a target-model variable.

    Returns:
        dict: Frequency of chain breaks as a dict in the form {s: f, ...},  where s
        is a variable in the source graph and float f the fraction
        of broken chains.

    Examples:
        This example embeds a single source node, 'a', as a chain of two target nodes (0, 1)
        and uses :func:`.chain_break_frequency` to show that out of two synthetic samples,
        one ([-1, +1]) represents a broken chain.

        >>> import numpy as np
        ...
        >>> samples = np.array([[-1, +1], [+1, +1]])
        >>> embedding = {'a': {0, 1}}
        >>> print(dwave.embedding.chain_break_frequency(samples, embedding)['a'])
        0.5


    """
    if isinstance(samples_like, dimod.SampleSet):
        labels = samples_like.variables
        samples = samples_like.record.sample
        num_occurrences = samples_like.record.num_occurrences
    else:
        samples, labels = dimod.as_samples(samples_like)
        num_occurrences = np.ones(samples.shape[0])

    if not all(v == idx for idx, v in enumerate(labels)):
        labels_to_idx = {v: idx for idx, v in enumerate(labels)}
        embedding = {
            v: {labels_to_idx[u]
                for u in chain}
            for v, chain in embedding.items()
        }

    if not embedding:
        return {}

    variables, chains = zip(*embedding.items())

    broken = broken_chains(samples, chains)

    return {
        v: float(np.average(broken[:, cidx], weights=num_occurrences))
        for cidx, v in enumerate(variables)
    }
示例#2
0
def chain_break_frequency(samples_like, embedding):
    """Determine the frequency of chain breaks in the given samples.

    Args:
        samples_like (samples_like/:obj:`dimod.SampleSet`):
            A collection of raw samples. 'samples_like' is an extension of NumPy's array_like.
            See :func:`dimod.as_samples`.

        embedding (dict):
            Mapping from source graph to target graph as a dict of form {s: {t, ...}, ...},
            where s is a source-model variable and t is a target-model variable.

    Returns:
        dict: Frequency of chain breaks as a dict in the form {s: f, ...},  where s
        is a variable in the source graph, and frequency, a float, is the fraction
        of broken chains.

    Examples:
        This example embeds a single source node, 'a', as a chain of two target nodes (0, 1)
        and uses :func:`.chain_break_frequency` to show that out of two synthetic samples,
        one ([-1, +1]) represents a broken chain.

        >>> import dimod
        >>> import numpy as np
        >>> samples = np.array([[-1, +1], [+1, +1]])
        >>> embedding = {'a': {0, 1}}
        >>> print(dimod.chain_break_frequency(samples, embedding)['a'])
        0.5


        This example embeds a single source node (0) as a chain of two target nodes (a, b)
        and uses :func:`.chain_break_frequency` to show that out of two samples in a
        dimod response, one ({'a': 1, 'b': 0}) represents a broken chain.

        >>> import dimod
        ...
        >>> response = dimod.SampleSet.from_samples([{'a': 1, 'b': 0}, {'a': 0, 'b': 0}],
        ...                                        {'energy': [1, 0]}, {}, dimod.BINARY)
        >>> embedding = {0: {'a', 'b'}}
        >>> print(dimod.chain_break_frequency(response, embedding)[0])
        0.5

    """
    if isinstance(samples_like, dimod.SampleSet):
        labels = samples_like.variables
        samples = samples_like.record.sample
    else:
        samples, labels = dimod.as_samples(samples_like)

    if not all(v == idx for idx, v in enumerate(labels)):
        labels_to_idx = {v: idx for idx, v in enumerate(labels)}
        embedding = {
            v: {labels_to_idx[u]
                for u in chain}
            for v, chain in embedding.items()
        }

    if not embedding:
        return {}

    variables, chains = zip(*embedding.items())

    broken = broken_chains(samples, chains)

    freq = {
        v: float(broken[:, cidx].mean())
        for cidx, v in enumerate(variables)
    }

    return freq
示例#3
0
def unembed_sampleset(target_sampleset,
                      embedding,
                      source_bqm,
                      chain_break_method=None,
                      chain_break_fraction=False,
                      return_embedding=False):
    """Unembed a sample set.

    Given samples from a target binary quadratic model (BQM), construct a sample
    set for a source BQM by unembedding.

    Args:
        target_sampleset (:obj:`dimod.SampleSet`):
            Sample set from the target BQM.

        embedding (dict):
            Mapping from source graph to target graph as a dict of form
            {s: {t, ...}, ...}, where s is a source variable and t is a target
            variable.

        source_bqm (:obj:`~dimod.BinaryQuadraticModel`):
            Source BQM.

        chain_break_method (function/list, optional):
            Method or methods used to resolve chain breaks. If multiple methods
            are given, the results are concatenated and a new field called
            "chain_break_method" specifying the index of the method is appended
            to the sample set.
            Defaults to :func:`~dwave.embedding.chain_breaks.majority_vote`.
            See :mod:`dwave.embedding.chain_breaks`.

        chain_break_fraction (bool, optional, default=False):
            Add a `chain_break_fraction` field to the unembedded :obj:`dimod.SampleSet`
            with the fraction of chains broken before unembedding.

        return_embedding (bool, optional, default=False):
            If True, the embedding is added to :attr:`dimod.SampleSet.info`
            of the returned sample set. Note that if an `embedding` key
            already exists in the sample set then it is overwritten.

    Returns:
        :obj:`.SampleSet`: Sample set in the source BQM.

    Examples:
       This example unembeds from a square target graph samples of a triangular
       source BQM.

        >>> # Triangular binary quadratic model and an embedding
        >>> J = {('a', 'b'): -1, ('b', 'c'): -1, ('a', 'c'): -1}
        >>> bqm = dimod.BinaryQuadraticModel.from_ising({}, J)
        >>> embedding = {'a': [0, 1], 'b': [2], 'c': [3]}
        >>> # Samples from the embedded binary quadratic model
        >>> samples = [{0: -1, 1: -1, 2: -1, 3: -1},  # [0, 1] is unbroken
        ...            {0: -1, 1: +1, 2: +1, 3: +1}]  # [0, 1] is broken
        >>> energies = [-3, 1]
        >>> embedded = dimod.SampleSet.from_samples(samples, dimod.SPIN, energies)
        >>> # Unembed
        >>> samples = dwave.embedding.unembed_sampleset(embedded, embedding, bqm)
        >>> samples.record.sample   # doctest: +SKIP
        array([[-1, -1, -1],
               [ 1,  1,  1]], dtype=int8)

    """

    if chain_break_method is None:
        chain_break_method = majority_vote
    elif isinstance(chain_break_method, abc.Sequence):
        # we want to apply multiple CBM and then combine
        samplesets = [
            unembed_sampleset(target_sampleset,
                              embedding,
                              source_bqm,
                              chain_break_method=cbm,
                              chain_break_fraction=chain_break_fraction)
            for cbm in chain_break_method
        ]
        sampleset = dimod.sampleset.concatenate(samplesets)

        # Add a new data field tracking which came from
        # todo: add this functionality to dimod
        cbm_idxs = np.empty(len(sampleset), dtype=int)

        start = 0
        for i, ss in enumerate(samplesets):
            cbm_idxs[start:start + len(ss)] = i
            start += len(ss)

        new = np.lib.recfunctions.append_fields(sampleset.record,
                                                'chain_break_method',
                                                cbm_idxs,
                                                asrecarray=True,
                                                usemask=False)

        return type(sampleset)(new, sampleset.variables, sampleset.info,
                               sampleset.vartype)

    variables = list(source_bqm.variables)  # need this ordered
    try:
        chains = [embedding[v] for v in variables]
    except KeyError:
        raise ValueError("given bqm does not match the embedding")

    record = target_sampleset.record

    unembedded, idxs = chain_break_method(target_sampleset, chains)

    reserved = {'sample', 'energy'}
    vectors = {
        name: record[name][idxs]
        for name in record.dtype.names if name not in reserved
    }

    if chain_break_fraction:
        broken = broken_chains(target_sampleset, chains)
        if broken.size:
            vectors['chain_break_fraction'] = broken.mean(axis=1)[idxs]
        else:
            vectors['chain_break_fraction'] = 0

    info = target_sampleset.info.copy()

    if return_embedding:
        embedding_context = dict(
            embedding=embedding,
            chain_break_method=chain_break_method.__name__)
        info.update(embedding_context=embedding_context)

    return dimod.SampleSet.from_samples_bqm((unembedded, variables),
                                            source_bqm,
                                            info=info,
                                            **vectors)
示例#4
0
def unembed_sampleset(target_sampleset,
                      embedding,
                      source_bqm,
                      chain_break_method=None,
                      chain_break_fraction=False,
                      return_embedding=False):
    """Unembed a samples set.

    Given samples from a target binary quadratic model (BQM), construct a sample
    set for a source BQM by unembedding.

    Args:
        target_sampleset (:obj:`dimod.SampleSet`):
            Sample set from the target BQM.

        embedding (dict):
            Mapping from source graph to target graph as a dict of form
            {s: {t, ...}, ...}, where s is a source variable and t is a target
            variable.

        source_bqm (:obj:`dimod.BinaryQuadraticModel`):
            Source BQM.

        chain_break_method (function, optional):
            Method used to resolve chain breaks.
            See :mod:`dwave.embedding.chain_breaks`.

        chain_break_fraction (bool, optional, default=False):
            Add a `chain_break_fraction` field to the unembedded :obj:`dimod.SampleSet`
            with the fraction of chains broken before unembedding.

        return_embedding (bool, optional, default=False):
            If True, the embedding is added to :attr:`dimod.SampleSet.info`
            of the returned sample set. Note that if an `embedding` key
            already exists in the sample set then it is overwritten.

    Returns:
        :obj:`.SampleSet`: Sample set in the source BQM.

    Examples:
       This example unembeds from a square target graph samples of a triangular
       source BQM.

        >>> # Triangular binary quadratic model and an embedding
        >>> J = {('a', 'b'): -1, ('b', 'c'): -1, ('a', 'c'): -1}
        >>> bqm = dimod.BinaryQuadraticModel.from_ising({}, J)
        >>> embedding = {'a': [0, 1], 'b': [2], 'c': [3]}
        >>> # Samples from the embedded binary quadratic model
        >>> samples = [{0: -1, 1: -1, 2: -1, 3: -1},  # [0, 1] is unbroken
        ...            {0: -1, 1: +1, 2: +1, 3: +1}]  # [0, 1] is broken
        >>> energies = [-3, 1]
        >>> embedded = dimod.SampleSet.from_samples(samples, dimod.SPIN, energies)
        >>> # Unembed
        >>> samples = dwave.embedding.unembed_sampleset(embedded, embedding, bqm)
        >>> samples.record.sample   # doctest: +SKIP
        array([[-1, -1, -1],
               [ 1,  1,  1]], dtype=int8)

    """

    if chain_break_method is None:
        chain_break_method = majority_vote

    variables = list(source_bqm.variables)  # need this ordered
    try:
        chains = [embedding[v] for v in variables]
    except KeyError:
        raise ValueError("given bqm does not match the embedding")

    record = target_sampleset.record

    unembedded, idxs = chain_break_method(target_sampleset, chains)

    reserved = {'sample', 'energy'}
    vectors = {
        name: record[name][idxs]
        for name in record.dtype.names if name not in reserved
    }

    if chain_break_fraction:
        vectors['chain_break_fraction'] = broken_chains(
            target_sampleset, chains).mean(axis=1)[idxs]

    info = target_sampleset.info.copy()

    if return_embedding:
        embedding_context = dict(
            embedding=embedding,
            chain_break_method=chain_break_method.__name__)
        info.update(embedding_context=embedding_context)

    return dimod.SampleSet.from_samples_bqm((unembedded, variables),
                                            source_bqm,
                                            info=info,
                                            **vectors)