Esempio n. 1
0
def bin_packing(
        num_items: int,
        seed: int = 32,
        weight_range: Tuple[int, int] = (10, 30),
) -> ConstrainedQuadraticModel:
    """Returns a constrained quadratic model encoding a bin packing problem

    Given the number of items, the code generates a random bin packing problem
    formulated as a Constrained Quadratic model. The weights for each item are
    integers uniformly drawn from in the weight_range. The bin capacity is set
    to num_items * mean(weights) / 5.

    Args:
        num_items: Number of items to choose from.

        seed: Seed for numpy random number  generator.

        weight_range: The range of the randomly generated weights for each item.

    Returns:
        The constrained quadratic model encoding the bin packing problem.
        Variables are labeled as y_{j} where y_{j} = 1 means that bin j has
        been used and x_{i}_{j} where x_{i}_{j} = 1 means that item i has been
        placed in bin j.

    """
    max_num_bins = num_items
    np.random.seed(seed)
    weights = list(np.random.randint(*weight_range, num_items))
    bin_capacity = int(num_items * np.mean(weights) / 5)
    model = ConstrainedQuadraticModel()

    obj = BinaryQuadraticModel(vartype='BINARY')
    y = {j: obj.add_variable(f'y_{j}') for j in range(max_num_bins)}

    for j in range(max_num_bins):
        obj.set_linear(y[j], 1)

    model.set_objective(obj)

    x = {(i, j): model.add_variable(f'x_{i}_{j}', vartype='BINARY')
         for i in range(num_items) for j in range(max_num_bins)}

    # Each item goes to one bin
    for i in range(num_items):
        model.add_constraint([(x[(i, j)], 1)
                              for j in range(max_num_bins)] + [(-1, )],
                             sense="==",
                             label='item_placing_{}'.format(i))

    # Bin capacity constraint
    for j in range(max_num_bins):
        model.add_constraint([(x[(i, j)], weights[i])
                              for i in range(num_items)] +
                             [(y[j], -bin_capacity)],
                             sense="<=",
                             label='capacity_bin_{}'.format(j))

    return model
Esempio n. 2
0
    def to_json(self):
        """
        Transform an Ising representation of a problem into a dimod.BinaryQuadraticModel (BQM) and return the serialized
        BQM.

        Returns
        -------
        bqm.to_serializable(): dict
            The serialized BQM
        """
        bqm = BinaryQuadraticModel(self.linear_dict, self.quadratic_dict, 0.0,
                                   dimod.SPIN)
        return bqm.to_serializable()
Esempio n. 3
0
def random_knapsack(
    num_items: int,
    seed: int = 32,
    value_range: Tuple[int, int] = (10, 30),
    weight_range: Tuple[int, int] = (10, 30),
    tightness_ratio: float = 0.5,
) -> ConstrainedQuadraticModel:
    """Returns a Constrained Quadratic Model encoding a knapsack problem.

    Given the number of items, the code generates a random knapsack problem,
    formulated as a Constrained Quadratic model. The capacity of the bin is set
    to be ``tightness_ratio`` times the sum of the weights.

    Args:
        num_items: Number of items to choose from.

        seed: Seed for numpy random number generator.

        value_range: The range of the randomly generated values for each item.

        weight_range: The range of the randomly generated weights for each item.

        tightness_ratio: ratio of capacity over sum of weights.

    Returns:
        The quadratic model encoding the knapsack problem. Variables are
        denoted as ``x_{i}`` where ``x_{i} == 1`` means that the item ``i`` has
        been placed in the knapsack.

    """

    rng = np.random.RandomState(seed)

    value = {i: rng.randint(*value_range) for i in range(num_items)}
    weight = {i: rng.randint(*weight_range) for i in range(num_items)}
    capacity = int(sum(weight.values()) * tightness_ratio)

    model = ConstrainedQuadraticModel()
    obj = BinaryQuadraticModel(vartype='BINARY')
    x = {i: obj.add_variable(f'x_{i}') for i in range(num_items)}

    for i in range(num_items):
        obj.set_linear(x[i], -value[i])

    model.set_objective(obj)
    constraint = [(x[i], weight[i])
                  for i in range(num_items)] + [(-capacity, )]
    model.add_constraint(constraint, sense="<=", label='capacity')

    return model
Esempio n. 4
0
def from_pandas_dataframe(bqm_df, offset=0.0, interactions=[]):
    """Build a binary quadratic model from a pandas dataframe.

    Args:
        bqm_df (:class:`pandas.DataFrame`):
            A pandas dataframe. The row and column indices should be that variables of the binary
            quadratic program. The values should be the coefficients of a qubo.

        offset (optional, default=0.0):
            The constant offset for the binary quadratic program.

        interactions (iterable, optional, default=[]):
            Any additional 0.0-bias interactions to be added to the binary quadratic model.

    Returns:
        :class:`.BinaryQuadraticModel`

    """
    bqm = BinaryQuadraticModel({}, {}, offset, Vartype.BINARY)

    for u, row in bqm_df.iterrows():
        for v, bias in row.iteritems():
            if u == v:
                bqm.add_variable(u, bias)
            elif bias:
                bqm.add_interaction(u, v, bias)

    for u, v in interactions:
        bqm.add_interaction(u, v, 0.0)

    return bqm
Esempio n. 5
0
    def sample_ising(self, h, J, **parameters):
        """Samples from an Ising model using an implemented sample method.

        Examples:
            This example implements a placeholder QUBO sampler and samples using
            the mixin Ising sampler.

            >>> import dimod
            >>> class ImplementQuboSampler(dimod.Sampler):
            ...     def sample_qubo(self, Q):
            ...         return dimod.Response.from_dicts([{1: -1, 2: +1}], {'energy': [-1.0]}) # Placeholder
            ...     @property
            ...     def properties(self):
            ...         return self._properties
            ...     @property
            ...     def parameters(self):
            ...         return dict()
            ...
            >>> sampler = ImplementQuboSampler()
            >>> h = {1: 0.5, 2: -1, 3: -0.75}
            >>> J = {}
            >>> res = sampler.sample_ising(h, J)
            >>> print(res)
            [[-1  1]]

        """
        bqm = BinaryQuadraticModel.from_ising(h, J)
        response = self.sample(bqm, **parameters)
        return response
Esempio n. 6
0
    def sample_qubo(self, Q, **parameters):
        """Sample from a QUBO using the implemented sample method.

        This method is inherited from the :class:`.Sampler` base class.

        Converts the QUBO into a :obj:`.BinaryQuadraticModel` and then
        calls :meth:`.sample`.

        Args:
            Q (dict):
                Coefficients of a quadratic unconstrained binary optimization
                (QUBO) problem. Should be a dict of the form `{(u, v): bias, ...}`
                where `u`, `v`, are binary-valued variables and `bias` is their
                associated coefficient.

            **kwargs:
                See the implemented sampling for additional keyword definitions.

        Returns:
            :obj:`.SampleSet`

        See also:
            :meth:`.sample`, :meth:`.sample_ising`

        """
        bqm = BinaryQuadraticModel.from_qubo(Q)
        return self.sample(bqm, **parameters)
Esempio n. 7
0
File: json.py Progetto: jmg/dimod
def bqm_decode_hook(dct):
    if 'bias' in dct:
        bias = dct['bias']
        if 'label' in dct:
            u = dct['label']
            if isinstance(u, list):
                u = tuple(u)
            return (u, bias)
        else:
            u = dct['label_head']
            v = dct['label_tail']
            if isinstance(u, list):
                u = tuple(u)
            if isinstance(v, list):
                v = tuple(v)
            return ((u, v), bias)

    elif 'linear_terms' in dct and 'quadratic_terms' in dct:
        return BinaryQuadraticModel(dict(dct['linear_terms']),
                                    dict(dct['quadratic_terms']),
                                    dct['offset'],
                                    Vartype[dct['variable_type']],
                                    **dct['info'])

    return dct
Esempio n. 8
0
def _spin_product(variables):
    """A BQM with a gap of 1 that represents the product of two spin variables.

    Note that spin-product requires an auxiliary variable.

    Args:
        variables (list):
            multiplier, multiplicand, product, aux

    Returns:
        :obj:`.BinaryQuadraticModel`

    """
    multiplier, multiplicand, product, aux = variables

    return BinaryQuadraticModel(
        {
            multiplier: -.5,
            multiplicand: -.5,
            product: -.5,
            aux: -1.
        }, {
            (multiplier, multiplicand): .5,
            (multiplier, product): .5,
            (multiplier, aux): 1.,
            (multiplicand, product): .5,
            (multiplicand, aux): 1.,
            (product, aux): 1.
        }, 2., Vartype.SPIN)
Esempio n. 9
0
    def sample_ising(self, h, J, **parameters):
        """Sample from an Ising model using the implemented sample method.

        This method is inherited from the :class:`.Sampler` base class.

        Converts the Ising model into a :obj:`.BinaryQuadraticModel` and then
        calls :meth:`.sample`.

        Args:
            h (dict/list):
                Linear biases of the Ising problem. If a dict, should be of the
                form `{v: bias, ...}` where is a spin-valued variable and `bias`
                is its associated bias. If a list, it is treated as a list of
                biases where the indices are the variable labels.

            J (dict[(variable, variable), bias]):
                Quadratic biases of the Ising problem.

            **kwargs:
                See the implemented sampling for additional keyword definitions.

        Returns:
            :obj:`.SampleSet`

        See also:
            :meth:`.sample`, :meth:`.sample_qubo`

        """
        bqm = BinaryQuadraticModel.from_ising(h, J)
        return self.sample(bqm, **parameters)
Esempio n. 10
0
    def sample_qubo(self, Q, **parameters):
        """Samples from a QUBO using an implemented sample method.

        Examples:
            This example implements a placeholder Ising sampler and samples using
            the mixin QUBO sampler.

            >>> import dimod
            >>> class ImplementIsingSampler(dimod.Sampler):
            ...     def sample_ising(self, h, J):
            ...         return dimod.Response.from_dicts([{1: -1, 2: +1}], {'energy': [-1.0]}) # Placeholder
            ...     @property
            ...     def properties(self):
            ...         return self._properties
            ...     @property
            ...     def parameters(self):
            ...         return dict()
            ...
            >>> sampler = ImplementIsingSampler()
            >>> Q = {(0, 0): -0.5, (0, 1): 1, (1, 1): -0.75}
            >>> res = sampler.sample_qubo(Q)
            >>> print(res)
            [[0 1]]


        """
        bqm = BinaryQuadraticModel.from_qubo(Q)
        response = self.sample(bqm, **parameters)
        return response
Esempio n. 11
0
    def sample_qubo(self, Q, num_samps=100):
        """
        Sample from the QUBO problem
        :param qubo: QUBO problem
        :type qubo: numpy dictionary
        :return: samples, energy, num_occurrences
        """
        self.num_samps = num_samps

        if not hasattr(self, 'sampler'):

            bqm = BinaryQuadraticModel.from_qubo(Q)

            # apply the embedding to the given problem to map it to the child sampler
            __, target_edgelist, target_adjacency = self.child.structure

            # add self-loops to edgelist to handle singleton variables
            source_edgelist = list(bqm.quadratic) + [(v, v)
                                                     for v in bqm.linear]

            # get the embedding
            embedding = minorminer.find_embedding(source_edgelist,
                                                  target_edgelist)

            if bqm and not embedding:
                raise ValueError("no embedding found")

            self.sampler = FixedEmbeddingComposite(self.child, embedding)

        response = self.sampler.sample_qubo(Q,
                                            chain_strength=self.chainstrength,
                                            num_reads=self.num_samps)

        return np.array(response.__dict__['_samples_matrix'].tolist()), response.__dict__['_data_vectors']["energy"], \
               response.__dict__['_data_vectors']["num_occurrences"]
Esempio n. 12
0
    def to_json(self):
        """Transform a QUBO dictionary into a dimod.BinaryQuadraticModel (BQM) and return the serialized BQM.

        Returns
        -------
        bqm.to_serializable(): dict
            The serialized BQM
        """
        linear = {}
        quadratic = {}
        for (a, b) in self.problem_dict.keys():
            if a == b:
                linear[a] = self.problem_dict[(a, b)]
            else:
                quadratic[(a, b)] = self.problem_dict[(a, b)]

        bqm = BinaryQuadraticModel(linear, quadratic, 0.0, dimod.BINARY)
        return bqm.to_serializable()
Esempio n. 13
0
def make_quadratic(poly, strength, vartype=None, bqm=None):
    """Create a binary quadratic model from a higher order polynomial.

    Args:
        poly (dict):
            A polynomial. Should be a dict of the form {term: bias, ...} where term is a tuple of
            variables and bias is their associated bias.

        strength (float):
            The strength of the reduction constraint. Insufficient strength can result in the
            binary quadratic model not having the same minimizations as the polynomial.

        vartype (:class:`.Vartype`, optional):
            The vartype of the polynomial. If a bqm is provided, then vartype is not required.

        bqm (:class:`.BinaryQuadraticModel`, optional):
            The terms of the reduced polynomial are added to this bqm. If not provided a new
            empty binary quadratic model is created.

    Returns:
        :class:`.BinaryQuadraticModel`

    Examples:

        >>> import dimod
        ...
        >>> poly = {(0,): -1, (1,): 1, (2,): 1.5, (0, 1): -1, (0, 1, 2): -2}
        >>> bqm = make_quadratic(poly, 5.0, dimod.SPIN)

    """

    if bqm is None:
        if vartype is None:
            raise ValueError("one of vartype and create_using must be provided")
        bqm = BinaryQuadraticModel.empty(vartype)
    else:
        if not isinstance(bqm, BinaryQuadraticModel):
            raise TypeError('create_using must be a BinaryQuadraticModel')
        if vartype is not None and vartype is not bqm.vartype:
            raise ValueError("one of vartype and create_using must be provided")
    bqm.info['reduction'] = {}

    new_poly = {}
    for term, bias in iteritems(poly):
        if len(term) == 0:
            bqm.add_offset(bias)
        elif len(term) == 1:
            v, = term
            bqm.add_variable(v, bias)
        else:
            new_poly[term] = bias

    return _reduce_degree(bqm, new_poly, vartype, strength)
Esempio n. 14
0
def from_numpy_matrix(mat, variable_order=None, offset=0.0, interactions=[]):
    """Build a binary quadratic model from a numpy matrix.

    Args:
        mat (:class:`numpy.matrix`):
            A square numpy matrix. The coefficients of a qubo.

        variable_order (list, optional):
            If variable_order is provided, provides the labels for the variables in the binary
            quadratic program, otherwise the row/column indices will be used. If variable_order
            is longer than the matrix, the extra values are ignored.

        offset (optional, default=0.0):
            The constant offset for the binary quadratic program.

        interactions (iterable, optional, default=[]):
            Any additional 0.0-bias interactions to be added to the binary quadratic model.

    Returns:
        :class:`.BinaryQuadraticModel`

    """
    import numpy as np

    if mat.ndim != 2:
        raise ValueError("expected input mat to be a square matrix")  # pragma: no cover

    num_row, num_col = mat.shape
    if num_col != num_row:
        raise ValueError("expected input mat to be a square matrix")  # pragma: no cover

    if variable_order is None:
        variable_order = list(range(num_row))

    bqm = BinaryQuadraticModel({}, {}, offset, Vartype.BINARY)

    for (row, col), bias in np.ndenumerate(mat):
        if row == col:
            bqm.add_variable(variable_order[row], bias)
        elif bias:
            bqm.add_interaction(variable_order[row], variable_order[col], bias)

    for u, v in interactions:
        bqm.add_interaction(u, v, 0.0)

    return bqm
Esempio n. 15
0
def make_quadratic_cqm(poly, vartype=None, cqm=None):
    """Create a constrained quadratic model from a higher order polynomial.

    Args:
        poly (dict):
            Polynomial as a dict of form {term: bias, ...}, where `term` is a tuple of
            variables and `bias` the associated bias.

        vartype (:class:`.Vartype`/str/set, optional):
            Variable type for the binary quadratic model. Accepted input values:

            * :class:`.Vartype.SPIN`, ``'SPIN'``, ``{-1, 1}``
            * :class:`.Vartype.BINARY`, ``'BINARY'``, ``{0, 1}``

            If `poly is a BinaryPolynomial , `vartype` is not required.

        cqm (:class:`.BinaryQuadraticModel`, optional):
            The terms of the reduced polynomial are added to this constrained quadratic model.
            If not provided, a new constrained quadratic model is created.

    Returns:
        :class:`.ConstrainedQuadraticModel`

    Examples:

        >>> poly = {(0,): -1, (1,): 1, (2,): 1.5, (0, 1): -1, (0, 1, 2): -2}
        >>> cqm = dimod.make_quadratic_cqm(poly, dimod.SPIN)

    """
    if not (vartype or isinstance(poly, BinaryPolynomial)):
        raise ValueError("can not infer vartype")
    cqm = cqm or ConstrainedQuadraticModel()
    vartype = vartype or poly.vartype
    poly = _init_binary_polynomial(poly, vartype)
    reduced_terms, constraints = reduce_binary_polynomial(poly)

    def var(x):
        return BinaryQuadraticModel({x: 1.0}, {}, 0.0, vartype)

    for (u, v), p in constraints:
        cqm.add_constraint(var(u) * var(v) - var(p) == 0,
                           label=f"'{u}'*'{v}' == '{p}'")

    obj = BinaryQuadraticModel(vartype=vartype)
    _init_objective(obj, reduced_terms)
    cqm.set_objective(obj + cqm.objective)

    return cqm
Esempio n. 16
0
File: json.py Progetto: todun/dimod
def dimod_object_hook(obj):
    """JSON-decoding for dimod objects.

    See Also:
        :class:`json.JSONDecoder` for using custom decoders.

    """
    if _is_sampleset_v2(obj):
        # in the future we could handle subtypes but right now we just have the
        # one
        return SampleSet.from_serializable(obj)
    elif _is_bqm(obj):
        # in the future we could handle subtypes but right now we just have the
        # one
        return BinaryQuadraticModel.from_serializable(obj)
    return obj
Esempio n. 17
0
    def sample_ising(self, h, J, offset=0, penalty_strength=1.0,
                     keep_penalty_variables=False,
                     discard_unsatisfied=False, **parameters):
        """ Sample from the problem provided by h, J, offset.

        Takes in linear variables in h and quadratic and higher order
        terms in J. Introducing penalties, reduces the higher-order problem
        into a quadratic problem and send it to its child sampler.

        Args:
            h (dict): linear biases corresponding to the HUBO form

            J (dict): higher order biases corresponding to the HUBO form

            offset (float, optional): constant energy offset

            penalty_strength (float, optional): Strength of the reduction constraint.
                Insufficient strength can result in the binary quadratic model
                not having the same minimization as the polynomial.

            keep_penalty_variables (bool, optional): default is True. if False
                will remove the variables used for penalty from the samples

            discard_unsatisfied (bool, optional): default is False. If True
                will discard samples that do not satisfy the penalty conditions.

            **parameters: Parameters for the sampling method, specified by
            the child sampler.

        Returns:
            :obj:`dimod.SampleSet`
        """

        # solve the problem on the child system

        bqm = BinaryQuadraticModel.from_ising(h, {})
        bqm = make_quadratic(J, penalty_strength, bqm=bqm)
        response = self.child.sample(bqm, **parameters)

        return polymorph_response(response, h, J, bqm,
                                  offset=offset,
                                  penalty_strength=penalty_strength,
                                  keep_penalty_variables=keep_penalty_variables,
                                  discard_unsatisfied=discard_unsatisfied)
Esempio n. 18
0
    def sample_qubo(self, Q, num_samps=100):
        """
        Sample from the QUBO problem
        :param qubo: QUBO problem
        :type qubo: numpy dictionary
        :return: samples, energy, num_occurrences
        """
        #print(Q)
        self.num_samps = num_samps

        if not hasattr(self, 'sampler'):

            bqm = BinaryQuadraticModel.from_qubo(Q)

            # apply the embedding to the given problem to map it to the child sampler
            __, target_edgelist, target_adjacency = self.child.structure

            # add self-loops to edgelist to handle singleton variables
            source_edgelist = list(bqm.quadratic) + [(v, v)
                                                     for v in bqm.linear]

            # get the embedding
            embedding = minorminer.find_embedding(source_edgelist,
                                                  target_edgelist)

            if bqm and not embedding:
                raise ValueError("no embedding found")

            self.sampler = FixedEmbeddingComposite(self.child, embedding)
        response = EmbeddingComposite(
            DWaveSampler(token="DEV-db4d47e5313cf3c52cac31dace7c5080a5ffc46d")
        ).sample_qubo(Q, num_reads=1000)
        #response = self.sampler.sample_qubo(Q, chain_strength=self.chainstrength, num_reads=self.num_samps)
        #for sample, energy, num_occurrences, chain_break_fraction in list(response.data()):
        #    print(sample, "Energy: ", energy, "Occurrences: ", num_occurrences)
        #print(response.samples()[0,[range(0,71)]])
        #print(response._asdict()['vectors']['energy'])
        #print(response._asdict()['vectors']['num_occurrences'])
        saempeul = np.empty((0, 72))
        for sample, in response.data(fields=['sample']):
            saempeul = np.append(saempeul, sample)
        #print(saempeul)
        return saempeul, response._asdict()['vectors']['energy']['data'], \
               response._asdict()['vectors']['num_occurrences']['data']
Esempio n. 19
0
def _binary_product(variables):
    """Create a bqm with a gap of 2 that represents the product of two variables.

    Args:
        variables (list):
            multiplier, multiplicand, product

    Returns:
        :obj:`.BinaryQuadraticModel`

    """
    multiplier, multiplicand, product = variables

    return BinaryQuadraticModel({multiplier: 0.0,
                                 multiplicand: 0.0,
                                 product: 3.0},
                                {(multiplier, multiplicand): 1.0,
                                 (multiplier, product): -2.0,
                                 (multiplicand, product): -2.0},
                                0.0,
                                Vartype.BINARY)
Esempio n. 20
0
def from_ising(h, J, offset=0.0):
    """Build a binary quadratic model from an Ising problem.


    Args:
        h (dict[variable, bias]/list[bias]):
            The linear biases of the Ising problem. If a list, the indices of the list are treated
            as the variable labels.

        J (dict[(variable, variable), bias]):
            The quadratic biases of the Ising problem.

        offset (optional, default=0.0):
            The constant offset applied to the model.

    Returns:
        :class:`.BinaryQuadraticModel`

    """
    if isinstance(h, list):
        h = dict(enumerate(h))

    return BinaryQuadraticModel(h, J, offset, Vartype.SPIN)
Esempio n. 21
0
def from_qubo(Q, offset=0.0):
    """Build a binary quadratic model from a qubo.

    Args:
        Q (dict):
            The qubo coefficients.

        offset (optional, default=0.0):
            The constant offset applied to the model.

    Returns:
        :class:`.BinaryQuadraticModel`

    """
    linear = {}
    quadratic = {}
    for (u, v), bias in iteritems(Q):
        if u == v:
            linear[u] = bias
        else:
            quadratic[(u, v)] = bias

    return BinaryQuadraticModel(linear, quadratic, offset, Vartype.BINARY)
Esempio n. 22
0
    def sample_ising(self, h, J, offset=0, scalar=None,
                     bias_range=1, quadratic_range=None,
                     ignored_variables=None, ignored_interactions=None,
                     ignore_offset=False, **parameters):
        """ Scale and sample from the problem provided by h, J, offset

        if scalar is not given, problem is scaled based on bias and quadratic
        ranges.

        Args:
            h (dict): linear biases

            J (dict): quadratic or higher order biases

            offset (float, optional): constant energy offset

            scalar (number):
                Value by which to scale the energy range of the binary quadratic model.

            bias_range (number/pair):
                Value/range by which to normalize the all the biases, or if
                `quadratic_range` is provided, just the linear biases.

            quadratic_range (number/pair):
                Value/range by which to normalize the quadratic biases.

            ignored_variables (iterable, optional):
                Biases associated with these variables are not scaled.

            ignored_interactions (iterable[tuple], optional):
                As an iterable of 2-tuples. Biases associated with these interactions are not scaled.

            ignore_offset (bool, default=False):
                If True, the offset is not scaled.

            **parameters:
                Parameters for the sampling method, specified by the child sampler.

        Returns:
            :obj:`dimod.SampleSet`

        """

        if any(len(inter) > 2 for inter in J):
            # handle HUBO
            import warnings
            msg = ("Support for higher order Ising models in ScaleComposite is "
                   "deprecated and will be removed in dimod 0.9.0. Please use "
                   "PolyScaleComposite.sample_hising instead.")
            warnings.warn(msg, DeprecationWarning)

            from dimod.reference.composites.higherordercomposites import PolyScaleComposite
            from dimod.higherorder.polynomial import BinaryPolynomial

            poly = BinaryPolynomial.from_hising(h, J, offset=offset)

            ignored_terms = set()
            if ignored_variables is not None:
                ignored_terms.update(frozenset(v) for v in ignored_variables)
            if ignored_interactions is not None:
                ignored_terms.update(frozenset(inter) for inter in ignored_interactions)
            if ignore_offset:
                ignored_terms.add(frozenset())

            return PolyScaleComposite(self.child).sample_poly(poly, scalar=scalar,
                                                              bias_range=bias_range,
                                                              poly_range=quadratic_range,
                                                              ignored_terms=ignored_terms,
                                                              **parameters)

        bqm = BinaryQuadraticModel.from_ising(h, J, offset=offset)
        return self.sample(bqm, scalar=scalar,
                           bias_range=bias_range,
                           quadratic_range=quadratic_range,
                           ignored_variables=ignored_variables,
                           ignored_interactions=ignored_interactions,
                           ignore_offset=ignore_offset, **parameters)
Esempio n. 23
0
def combinations(n, k, strength=1, vartype=BINARY):
    r"""Generate a BQM that is minimized when k of n variables are selected.

    More fully, generates a binary quadratic model (BQM) that is minimized for
    each of the k-combinations of its variables.

    The energy for the BQM is given by
    :math:`(\sum_{i} x_i - k)^2`.

    Args:
        n (int/list/set):
            If n is an integer, variables are labelled [0, n-1]. If n is a list
            or set, variables are labelled accordingly.

        k (int):
            The generated BQM has 0 energy when any k of its variables are 1.

        strength (number, optional, default=1):
            The energy of the first excited state of the BQM.

        vartype (:class:`.Vartype`/str/set):
            Variable type for the BQM. Accepted input values:

            * :class:`.Vartype.SPIN`, ``'SPIN'``, ``{-1, 1}``
            * :class:`.Vartype.BINARY`, ``'BINARY'``, ``{0, 1}``

    Returns:
        :obj:`.BinaryQuadraticModel`

    Examples:

        >>> bqm = dimod.generators.combinations(['a', 'b', 'c'], 2)
        >>> bqm.energy({'a': 1, 'b': 0, 'c': 1})
        0.0
        >>> bqm.energy({'a': 1, 'b': 1, 'c': 1})
        1.0

        >>> bqm = dimod.generators.combinations(5, 1)
        >>> bqm.energy({0: 0, 1: 0, 2: 1, 3: 0, 4: 0})
        0.0
        >>> bqm.energy({0: 0, 1: 0, 2: 1, 3: 1, 4: 0})
        1.0

        >>> bqm = dimod.generators.combinations(['a', 'b', 'c'], 2, strength=3.0)
        >>> bqm.energy({'a': 1, 'b': 0, 'c': 1})
        0.0
        >>> bqm.energy({'a': 1, 'b': 1, 'c': 1})
        3.0

    """
    if isinstance(n, abc.Sized) and isinstance(n, abc.Iterable):
        # what we actually want is abc.Collection but that doesn't exist in
        # python2
        variables = n
    else:
        try:
            variables = range(n)
        except TypeError:
            raise TypeError('n should be a collection or an integer')

    if k > len(variables) or k < 0:
        raise ValueError("cannot select k={} from {} variables".format(k, len(variables)))

    # (\sum_i x_i - k)^2
    #     = \sum_i x_i \sum_j x_j - 2k\sum_i x_i + k^2
    #     = \sum_{i,j} x_ix_j + (1 - 2k)\sum_i x_i + k^2
    lbias = float(strength*(1 - 2*k))
    qbias = float(2*strength)

    bqm = BinaryQuadraticModel.empty(BINARY)
    bqm.add_variables_from(((v, lbias) for v in variables))
    bqm.add_interactions_from(((u, v, qbias) for u, v in itertools.combinations(variables, 2)))
    bqm.offset += strength*(k**2)

    return bqm.change_vartype(vartype, inplace=True)
Esempio n. 24
0
    def sample_ising(self,
                     h,
                     J,
                     offset=0,
                     scalar=None,
                     bias_range=1,
                     quadratic_range=None,
                     ignored_variables=None,
                     ignored_interactions=None,
                     ignore_offset=False,
                     **parameters):
        """ Scale and sample from the problem provided by h, J, offset

        if scalar is not given, problem is scaled based on bias and quadratic
        ranges.

        Args:
            h (dict): linear biases

            J (dict): quadratic or higher order biases

            offset (float, optional): constant energy offset

            scalar (number):
                Value by which to scale the energy range of the binary quadratic model.

            bias_range (number/pair):
                Value/range by which to normalize the all the biases, or if
                `quadratic_range` is provided, just the linear biases.

            quadratic_range (number/pair):
                Value/range by which to normalize the quadratic biases.

            ignored_variables (iterable, optional):
                Biases associated with these variables are not scaled.

            ignored_interactions (iterable[tuple], optional):
                As an iterable of 2-tuples. Biases associated with these interactions are not scaled.

            ignore_offset (bool, default=False):
                If True, the offset is not scaled.

            **parameters:
                Parameters for the sampling method, specified by the child sampler.

        Returns:
            :obj:`dimod.SampleSet`

        """

        # if quadratic, create a bqm and send to sample

        if max(map(len, J.keys())) == 2:
            bqm = BinaryQuadraticModel.from_ising(h, J, offset=offset)
            return self.sample(bqm,
                               scalar=scalar,
                               bias_range=bias_range,
                               quadratic_range=quadratic_range,
                               ignored_variables=ignored_variables,
                               ignored_interactions=ignored_interactions,
                               ignore_offset=ignore_offset,
                               **parameters)

        # handle HUBO

        ignored_variables, ignored_interactions = _check_params(
            ignored_variables, ignored_interactions)

        child = self.child
        h_sc, J_sc, offset_sc = _scaled_hubo(h, J, offset, scalar, bias_range,
                                             quadratic_range,
                                             ignored_variables,
                                             ignored_interactions,
                                             ignore_offset)
        response = child.sample_ising(h_sc,
                                      J_sc,
                                      offset=offset_sc,
                                      **parameters)

        poly = _relabeled_poly(h, J, response.variables.index)
        response.record.energy = np.add(
            poly_energies(response.record.sample, poly), offset)
        return response
Esempio n. 25
0
def embed_qubo(source_Q, embedding, target_adjacency, chain_strength=1.0):
    """Embed a QUBO onto a target graph.

    Args:
        source_Q (dict[(variable, variable), bias]):
            Coefficients of a quadratic unconstrained binary optimization (QUBO) model.

        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.

        target_adjacency (dict/:class:`networkx.Graph`):
            Adjacency of the target graph as a dict of form {t: Nt, ...},
            where t is a target-graph variable and Nt is its set of neighbours.

        chain_strength (float, optional):
            Magnitude of the quadratic bias (in SPIN-space) applied between variables to form a chain. Note
            that the energy penalty of chain breaks is 2 * `chain_strength`.

    Returns:
        dict[(variable, variable), bias]: Quadratic biases of the target QUBO.

    Examples:
        This example embeds a square source graph onto fully connected :math:`K_5` graph.
        Embedding is accomplished by an edge deletion operation on the target graph: target-node
        0 is not used.

        >>> import dimod
        >>> import networkx as nx
        >>> # QUBO problem for a square graph
        >>> Q = {(1, 1): -4.0, (1, 2): 4.0, (2, 2): -4.0, (2, 3): 4.0,
        ...      (3, 3): -4.0, (3, 4): 4.0, (4, 1): 4.0, (4, 4): -4.0}
        >>> # Target graph is a fully connected k5 graph
        >>> K_5 = nx.complete_graph(5)
        >>> 0 in K_5
        True
        >>> # Embedding from source to target graph
        >>> embedding = {1: {4}, 2: {3}, 3: {1}, 4: {2}}
        >>> # Embed the QUBO
        >>> target_Q = dimod.embed_qubo(Q, embedding, K_5)
        >>> (0, 0) in target_Q
        False
        >>> target_Q     # doctest: +SKIP
        {(1, 1): -4.0,
         (1, 2): 4.0,
         (2, 2): -4.0,
         (2, 4): 4.0,
         (3, 1): 4.0,
         (3, 3): -4.0,
         (4, 3): 4.0,
         (4, 4): -4.0}

        This example embeds a square graph onto the target graph of a dimod reference structured
        sampler, `StructureComposite`, using the dimod reference `ExactSolver` sampler with a
        fully connected :math:`K_5` graph specified.

        >>> import dimod
        >>> import networkx as nx
        >>> # QUBO problem for a square graph
        >>> Q = {(1, 1): -4.0, (1, 2): 4.0, (2, 2): -4.0, (2, 3): 4.0,
        ...      (3, 3): -4.0, (3, 4): 4.0, (4, 1): 4.0, (4, 4): -4.0}
        >>> # Structured dimod sampler with a structure defined by a K5 graph
        >>> sampler = dimod.StructureComposite(dimod.ExactSolver(), list(K_5.nodes), list(K_5.edges))
        >>> sampler.adjacency      # doctest: +SKIP
        {0: {1, 2, 3, 4},
         1: {0, 2, 3, 4},
         2: {0, 1, 3, 4},
         3: {0, 1, 2, 4},
         4: {0, 1, 2, 3}}
        >>> # Embedding from source to target graph
        >>> embedding = {0: [4], 1: [3], 2: [1], 3: [2], 4: [0]}
        >>> # Embed the QUBO
        >>> target_Q = dimod.embed_qubo(Q, embedding, sampler.adjacency)
        >>> # Sample
        >>> response = sampler.sample_qubo(target_Q)
        >>> for datum in response.data():   # doctest: +SKIP
        ...     print(datum)
        ...
        Sample(sample={1: 0, 2: 1, 3: 1, 4: 0}, energy=-8.0)
        Sample(sample={1: 1, 2: 0, 3: 0, 4: 1}, energy=-8.0)
        Sample(sample={1: 1, 2: 0, 3: 0, 4: 0}, energy=-4.0)
        Sample(sample={1: 1, 2: 1, 3: 0, 4: 0}, energy=-4.0)
        Sample(sample={1: 0, 2: 1, 3: 0, 4: 0}, energy=-4.0)
        Sample(sample={1: 1, 2: 1, 3: 1, 4: 0}, energy=-4.0)
        >>> # Snipped above response for brevity

    """
    source_bqm = BinaryQuadraticModel.from_qubo(source_Q)
    target_bqm = embed_bqm(source_bqm, embedding, target_adjacency, chain_strength=chain_strength)
    target_Q, __ = target_bqm.to_qubo()
    return target_Q
Esempio n. 26
0
def embed_ising(souce_h, source_J, embedding, target_adjacency, chain_strength=1.0):
    """Embed an Ising problem onto a target graph.

    Args:
        source_h (dict[variable, bias]/list[bias]):
            Linear biases of the Ising problem. If a list, the list's indices are used as
            variable labels.

        source_J (dict[(variable, variable), bias]):
            Quadratic biases of the Ising problem.

        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.

        target_adjacency (dict/:class:`networkx.Graph`):
            Adjacency of the target graph as a dict of form {t: Nt, ...},
            where t is a target-graph variable and Nt is its set of neighbours.

        chain_strength (float, optional):
            Magnitude of the quadratic bias (in SPIN-space) applied between variables to form a chain. Note
            that the energy penalty of chain breaks is 2 * `chain_strength`.

    Returns:
        tuple: A 2-tuple:

            dict[variable, bias]: Linear biases of the target Ising problem.

            dict[(variable, variable), bias]: Quadratic biases of the target Ising problem.

    Examples:
        This example embeds a fully connected :math:`K_3` graph onto a square target graph.
        Embedding is accomplished by an edge contraction operation on the target graph: target-nodes
        2 and 3 are chained to represent source-node c.

        >>> import dimod
        >>> import networkx as nx
        >>> # Ising problem for a triangular source graph
        >>> h = {}
        >>> J = {('a', 'b'): 1, ('b', 'c'): 1, ('a', 'c'): 1}
        >>> # Target graph is a square graph
        >>> target = nx.cycle_graph(4)
        >>> # Embedding from source to target graph
        >>> embedding = {'a': {0}, 'b': {1}, 'c': {2, 3}}
        >>> # Embed the Ising problem
        >>> target_h, target_J = dimod.embed_ising(h, J, embedding, target)
        >>> target_J[(0, 1)] == J[('a', 'b')]
        True
        >>> target_J        # doctest: +SKIP
        {(0, 1): 1.0, (0, 3): 1.0, (1, 2): 1.0, (2, 3): -1.0}

        This example embeds a fully connected :math:`K_3` graph onto the target graph
        of a dimod reference structured sampler, `StructureComposite`, using the dimod reference
        `ExactSolver` sampler with a square graph specified. Target-nodes 2 and 3 are chained to
        represent source-node c.

        >>> import dimod
        >>> # Ising problem for a triangular source graph
        >>> h = {}
        >>> J = {('a', 'b'): 1, ('b', 'c'): 1, ('a', 'c'): 1}
        >>> # Structured dimod sampler with a structure defined by a square graph
        >>> sampler = dimod.StructureComposite(dimod.ExactSolver(), [0, 1, 2, 3], [(0, 1), (1, 2), (2, 3), (0, 3)])
        >>> # Embedding from source to target graph
        >>> embedding = {'a': {0}, 'b': {1}, 'c': {2, 3}}
        >>> # Embed the Ising problem
        >>> target_h, target_J = dimod.embed_ising(h, J, embedding, sampler.adjacency)
        >>> # Sample
        >>> response = sampler.sample_ising(target_h, target_J)
        >>> for sample in response.samples(n=3, sorted_by='energy'):   # doctest: +SKIP
        ...     print(sample)
        ...
        {0: 1, 1: -1, 2: -1, 3: -1}
        {0: 1, 1: 1, 2: -1, 3: -1}
        {0: -1, 1: 1, 2: -1, 3: -1}

    """
    source_bqm = BinaryQuadraticModel.from_ising(souce_h, source_J)
    target_bqm = embed_bqm(source_bqm, embedding, target_adjacency, chain_strength=chain_strength)
    target_h, target_J, __ = target_bqm.to_ising()
    return target_h, target_J
Esempio n. 27
0
 def get_qubo_embedding(self, Q, **parameters):
     """Retrieve or create a minor-embedding from QUBO
     """
     bqm = BinaryQuadraticModel.from_qubo(Q)
     embedding = self.get_embedding(bqm, **parameters)
     return embedding
Esempio n. 28
0
 def get_ising_embedding(self, h, J, **parameters):
     """Retrieve or create a minor-embedding from Ising model
     """
     bqm = BinaryQuadraticModel.from_ising(h, J)
     embedding = self.get_embedding(bqm, **parameters)
     return embedding
Esempio n. 29
0
 def sample_qubo(self, Q, **parameters):
     """Samples from the given QUBO using the instantiated sample method."""
     bqm = BinaryQuadraticModel.from_qubo(Q)
     response = self.sample(bqm, **parameters)
     return response
Esempio n. 30
0
 def sample_ising(self, h, J, **parameters):
     """Samples from the given Ising model using the instantiated sample method."""
     bqm = BinaryQuadraticModel.from_ising(h, J)
     response = self.sample(bqm, **parameters)
     return response