Пример #1
0
def build_cqm(W, C, n, p, a, verbose=True):
    """Builds constrained quadratic model representing the optimization problem.

    Args:
        - W: Numpy matrix. Represents passenger demand. Normalized with total demand equal to 1.
        - C: Numpy matrix. Represents airline leg cost.
        - n: Int. Number of cities in play.
        - p: Int. Number of hubs airports allowed.
        - a: Float in [0.0, 1.0]. Discount allowed for hub-hub legs.
        - verbose: Print to command-line for user.

    Returns:
        - cqm: ConstrainedQuadraticModel representing the optimization problem.
    """

    if verbose:
        print("\nBuilding CQM...\n")

    # Initialize the CQM object
    cqm = ConstrainedQuadraticModel()

    # Objective: Minimize cost. min c'x+x'Qx
    # See reference paper for full explanation.
    M = np.sum(W, axis=0) + np.sum(W, axis=1)
    Q = a * np.kron(W, C)

    linear = ((M * C.T).T).flatten()

    obj = BinaryQuadraticModel(linear, Q, 'BINARY')
    obj.relabel_variables({
        idx: (i, j)
        for idx, (i, j) in enumerate(
            (i, j) for i in range(n) for j in range(n))
    })

    cqm.set_objective(obj)

    # Add constraint to make variables discrete
    for v in range(n):
        cqm.add_discrete([(v, i) for i in range(n)])

    # Constraint: Every leg must connect to a hub.
    for i in range(n):
        for j in range(n):
            if i != j:
                c1 = BinaryQuadraticModel('BINARY')
                c1.add_linear((i, j), 1)
                c1.add_quadratic((i, j), (j, j), -1)
                cqm.add_constraint(c1 == 0)

    # Constraint: Exactly p hubs required.
    linear_terms = {(i, i): 1.0 for i in range(n)}
    c2 = BinaryQuadraticModel('BINARY')
    c2.add_linear_from(linear_terms)
    cqm.add_constraint(c2 == p, label='num hubs')

    return cqm
Пример #2
0
def build_knapsack_cqm(costs, weights, max_weight):
    """Construct a CQM for the knapsack problem.

    Args:
        costs (array-like):
            Array of costs for the items.
        weights (array-like):
            Array of weights for the items.
        max_weight (int):
            Maximum allowable weight for the knapsack.

    Returns:
        Constrained quadratic model instance that represents the knapsack problem.
    """
    num_items = len(costs)
    print("\nBuilding a CQM for {} items.".format(str(num_items)))

    cqm = ConstrainedQuadraticModel()
    obj = BinaryQuadraticModel(vartype='BINARY')
    constraint = QuadraticModel()

    for i in range(num_items):
        # Objective is to maximize the total costs
        obj.add_variable(i)
        obj.set_linear(i, -costs[i])
        # Constraint is to keep the sum of items' weights under or equal capacity
        constraint.add_variable('BINARY', i)
        constraint.set_linear(i, weights[i])

    cqm.set_objective(obj)
    cqm.add_constraint(constraint, sense="<=", rhs=max_weight, label='capacity')

    return cqm
Пример #3
0
    def min_time_limit(self, cqm: dimod.ConstrainedQuadraticModel) -> float:
        """Return the minimum `time_limit` accepted for the given problem."""

        # todo: remove the hard-coded defaults
        num_variables_multiplier = self.properties.get('num_variables_multiplier', 1.57e-04)
        num_biases_multiplier = self.properties.get('num_biases_multiplier', 4.65e-06)
        num_constraints_multiplier = self.properties.get('num_constraints_multiplier', 6.44e-09)
        minimum_time_limit = self.properties['minimum_time_limit_s']

        num_variables = len(cqm.variables)
        num_constraints = len(cqm.constraints)
        num_biases = cqm.num_biases()

        return max(
            num_variables_multiplier * num_variables +
            num_biases_multiplier * num_biases +
            num_constraints_multiplier * num_variables * num_constraints,
            minimum_time_limit
            )
Пример #4
0
    def sample_cqm(self,
                   cqm: dimod.ConstrainedQuadraticModel,
                   time_limit: Optional[float] = None,
                   **kwargs):
        """Sample from the specified constrained quadratic model.

        Args:
            cqm (:obj:`dimod.ConstrainedQuadraticModel`):
                Constrained quadratic model (CQM).

            time_limit (int, optional):
                Maximum run time, in seconds, to allow the solver to work on the
                problem. Must be at least the minimum required for the problem,
                which is calculated and set by default.

                :meth:`~dwave.system.samplers.LeapHybridCQMSampler.min_time_limit`
                calculates (and describes) the minimum time for your problem.

            **kwargs:
                Optional keyword arguments for the solver, specified in
                :attr:`~dwave.system.samplers.LeapHybridCQMSampler.parameters`.

        Returns:
            :class:`~dimod.SampleSet`: Sample set constructed from a (non-blocking)
            :class:`~concurrent.futures.Future`-like object.

        Examples:
            See the example in :class:`LeapHybridCQMSampler`.

        """

        if not isinstance(cqm, dimod.ConstrainedQuadraticModel):
            raise TypeError(
                "first argument 'cqm' must be a ConstrainedQuadraticModel, "
                f"recieved {type(cqm).__name__}")

        if time_limit is None:
            time_limit = self.min_time_limit(cqm)
        elif time_limit < self.min_time_limit(cqm):
            raise ValueError("the minimum time limit for this problem is "
                             f"{self.min_time_limit(cqm)} seconds "
                             f"({time_limit}s provided), "
                             "see .min_time_limit method")

        contact_sales_str = "Contact D-Wave at [email protected] if your " + \
                            "application requires scale or performance that " + \
                            "exceeds the currently advertised capabilities of " + \
                            "this hybrid solver."

        if len(cqm.constraints
               ) > self.properties['maximum_number_of_constraints']:
            raise ValueError(
                "constrained quadratic model must have "
                f"{self.properties['maximum_number_of_constraints']} or fewer "
                f"constraints; given model has {len(cqm.constraints)}. "
                f"{contact_sales_str}")

        if len(cqm.variables) > self.properties['maximum_number_of_variables']:
            raise ValueError(
                "constrained quadratic model must have "
                f"{self.properties['maximum_number_of_variables']} or fewer "
                f"variables; given model has {len(cqm.variables)}. "
                f"{contact_sales_str}")

        if cqm.num_biases() > self.properties['maximum_number_of_biases']:
            raise ValueError(
                "constrained quadratic model must have "
                f"{self.properties['maximum_number_of_biases']} or fewer "
                f"biases; given model has {cqm.num_biases()}. "
                f"{contact_sales_str}")

        if cqm.num_quadratic_variables(
        ) > self.properties['maximum_number_of_quadratic_variables']:
            raise ValueError(
                "constrained quadratic model must have "
                f"{self.properties['maximum_number_of_quadratic_variables']} "
                "or fewer variables with at least one quadratic bias across "
                "all constraints; given model has "
                f"{cqm.num_quadratic_variables()}. "
                f"{contact_sales_str}")

        return self.solver.sample_cqm(cqm, time_limit=time_limit,
                                      **kwargs).sampleset