The bin packing problem,
BPP,
seeks to find the smallest number of bins that will fit
a set of weighted items given that each bin has a weight capacity.
Parameters:
weights – Weight per item as a 1D array-like (row vector or Python list).
Weights can be any non-negative number.
capacity – Maximum capacity of each bin. Must be a positive number.
Returns:
A model encoding the BPP problem.
Notes
The model uses a DisjointBitSets
class as the decision variable being optimized, with permutations of its
bit sets representing various packings for each bin.
Examples
This example finds how many bins are needed to pack four items with
various weights into bins with maximum capacity 7.
An example feasible solution might be four bit sets (for four items the
maximum possible number of bins is four) of four bits each (a bit per
item), with \(1.0\) signifying placement of the corresponding item
in the corresponding bin,
where here the second item with weight 5 is in one bin and the remaining
items are in a second bin. The objective value for this solution is 2,
as shown in the following code.
The iter_decisions() method
obtains the decision variables of the generated model.
>>> items=next(model.iter_decisions())
To test the solution above, set it in the model as the state of the
decision variable. Skip these next lines if you have submitted your
model to the Leaphybrid
nonlinear solver.
You can use the iter_constraints()
method to check feasibility of constructed or returned solutions. Here,
the number of states (size()) is
set to 1 for the constructed solution so a single value of the
objective property is printed.
>>> withmodel.lock():... capacity_constraint=next(model.iter_constraints())... foriinrange(model.states.size()):... ifcapacity_constraint.state(i):# Filter on feasibility... print((f"Objective value #{i} is {model.objective.state(i)} for packing\n"... f" {[b.state(i).tolist()forbinitems.iter_successors()]}"))Objective value #0 is 2.0 for packing [[0.0, 1.0, 0.0, 0.0], [1.0, 0.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]
Generate a model encoding a capacitated vehicle routing problem.
The capacitated vehicle routing problem,
CVRP,
is to find the shortest possible routes for a fleet of vehicles delivering
to multiple customer locations from a central depot. Vehicles have a
specified delivery capacity, and on the routes to locations and then back
to the depot, no vehicle is allowed to exceed its carrying capacity.
Parameters:
demand – Customer demand, as an array-like. If distances is specified,
the first element must be zero. If distances is not specified
and the first element is zero, [locations_x[0],locations_y[0]]
must be the location of the depot. Elements other than the first
must be positive numbers.
number_of_vehicles – Number of available vehicles, as a positive integer.
vehicle_capacity – Maximum capacity for any vehicle. The total delivered demand by any
vehicle on any route must not exceed this value.
distances – Distances between all the problem’s locations, as an array-like
of positive numbers, including both customer sites and the depot.
When specified, the first element of demand must be zero and
specifying Xcoordinates or Xcoordinates is not supported
locations_x – X coordinates, as an array-like, of locations for customers, and
optionally the depot. When specified, 2D Euclidean distances are
calculated and specifying distances is not supported. If the
first element represents the X coordinate of the depot, the first
element of demand must be zero.
locations_y – Y coordinates, as an array-like, of locations for customers, and
optionally the depot. When specified, 2D Euclidean distances are
calculated and specifying distances is not supported. If the
first element represents the Y coordinate of the depot, the first
element of demand must be zero.
depot_x_y – Location of the depot, as an array-like of exactly two elements,
[X,Y]. Required if the first element of demand is nonzero
and distances is not specified; not allowed otherwise.
Returns:
A model encoding the CVRP problem.
Notes
The model uses a DisjointLists
class as the decision variable being optimized, with permutations of its
sublists representing various itineraries for each vehicle.
Examples
This example finds delivery routes for two vehicles delivering from a
depot to nine sites with maximum vehicle capacity 200.
meaning one vehicle visits customer sites \(2, 7, 1, 5\) and the
other vehicle visits the remaining sites. The objective value for this
solution is \(\approx 424\), as shown in the following code.
The iter_decisions() method
obtains the decision variables of the generated model.
>>> routes=next(model.iter_decisions())
To test the solution above, set it in the model as the state of the
decision variable. Skip these next lines if you have submitted your
model to the Leaphybrid
nonlinear solver.
You can use the iter_constraints()
method to check feasibility of constructed or returned solutions. Here,
the number of states (size()) is
set to 1 for the constructed solution so a single value of the
objective property is printed.
>>> withmodel.lock():... capacity_constraint=next(model.iter_constraints())... foriinrange(model.states.size()):... ifcapacity_constraint.state(i):# Filter on feasibility... print((f"Objective value #{i} is {model.objective.state(i).round(2)} for routes\n"... f" {[r.state(i).tolist()forrinroutes.iter_successors()]}"))Objective value #0 is 423.8 for routes [[2.0, 7.0, 1.0, 5.0], [4.0, 3.0, 8.0, 6.0, 0.0]]
Generate a model encoding a capacitated vehicle routing problem with time windows.
The capacitated vehicle routing problem with time windows,
CVRPTW,
is to find the shortest possible routes for a fleet of vehicles delivering
to multiple customer locations from a central depot. Each customer should
be served after their time window opens and before it closes. Vehicles have
a specified delivery capacity, and on the routes to locations and then back
to the depot, no vehicle is allowed to exceed its carrying capacity.
Parameters:
demand – Customer demand, as an array-like. The first element is the depot
and must be zero.
number_of_vehicles – Number of available vehicles, as a positive integer.
vehicle_capacity – Maximum capacity for any vehicle. The total delivered demand by any
vehicle on any route must not exceed this value.
time_distances – Time distances between all the problem’s locations, as an
array-like of positive numbers, including both customer sites and
the depot. The first row and column of the distance matrix are
customer distances from the depot.
time_window_open – Opening time for each customer, as an array-like. The first
element is the depot.
time_window_close – Closing time for each customer, as an array-like. The first
element is the depot. Arrival at each customer \(i\) must occur
earlier than time_window_close[i]-service_time[i] to enable
the delivery to be serviced before the window closes.
service_time – Time it takes to serve each customer, as an array-like. The first
element is the depot and must be zero. For feasible solutions,
service_time[i]<=time_window_close[i]-time_window_open[i]
for each customer \(i\).
Returns:
A model encoding the CVRPTW problem.
Notes
The model uses a DisjointLists
class as the decision variable being optimized, with permutations of its
sublists representing various itineraries for each vehicle.
Examples
This example finds delivery routes for two vehicles delivering from a
depot to three sites with maximum vehicle capacity 40 and varying
opening,closing, and service times.
meaning one vehicle visits customer sites \(0, 2\) and the
other vehicle visits site \(1\). The objective value for this
solution is \(\approx 103\), as shown in the following code.
The iter_decisions() method
obtains the decision variables of the generated model.
>>> routes=next(model.iter_decisions())
To test the solution above, set it in the model as the state of the
decision variable. Skip these next lines if you have submitted your
model to the Leaphybrid
nonlinear solver.
You can use the iter_constraints()
method to check feasibility of constructed or returned solutions. Here,
the number of states (size()) is
set to 1 for the constructed solution so a single value of the
objective property is printed.
>>> withmodel.lock():... foriinrange(model.states.size()):... ifall(sym.state(i)forsyminmodel.iter_constraints()):# Filter feasibility... print((f"Objective value #{i} is {model.objective.state(i).round(2)} for routes\n"... f" {[r.state(i).tolist()forrinroutes]}"))Objective value #0 is 103.0 for routes [[0.0, 2.0], [1.0]]
Generate a model encoding a flow-shop scheduling problem.
Flow-shop scheduling
is a variant of the renowned job_shop_scheduling() optimization problem.
Given \(n\) jobs to schedule on \(m\) machines, with specified
processing times for each job per machine, minimize the makespan (the total
length of the schedule for processing all the jobs). For every job, the
\(i\)-th operation is executed on the \(i\)-th machine. No machine
can perform more than one operation simultaneously.
E. Taillard
provides benchmark instances compatible with this generator.
Note
There are many ways to model flow-shop scheduling. The model returned
by this function may or may not give the best performance for your
problem.
Parameters:
processing_times – Processing times, as an \(m \times n\)array-like of
integers, where processing_times[m,n] is the time job
\(n\) is on machine \(m\).
Returns:
A model encoding the flow-shop scheduling problem.
Notes
The model uses a ListVariable
class as the decision variable being optimized, with permutations of its
integer values representing various job orderings.
Examples
This example creates a model for a flow-shop-scheduling problem
with three jobs on two machines. For example, the first job
requires processing for 20 time units on the second machine in
the flow of operations.
An example feasible solution might be \([1, 0, 2]\), meaning the
order of jobs is job 1 first, job 0 second, and job 2 last. The
objective value (makespan) for this solution is \(50\), as shown in
the following code.
The iter_decisions() method
obtains the decision variables of the generated model.
>>> order=next(model.iter_decisions())
To test the solution above, set it in the model as the state of the
decision variable. Skip these next lines if you have submitted your
model to the Leaphybrid
nonlinear solver.
Here, the number of states
(size()) is set to 1 for the
constructed solution so a single value of the
objective property is printed.
>>> withmodel.lock():... foriinrange(model.states.size()):... print((f"Order #{i} is {order.state(i).tolist()} with makespan "... f"{model.objective.state(i).round(2)}"))Order #0 is [1.0, 0.0, 2.0] with makespan 50.0
Generate a model encoding a job-shop scheduling problem.
There are many variants of
job-shop scheduling,
a problem where given \(n\) jobs to schedule on \(m\) machines, with
specified processing times for each job per machine, the aim is to minimize
the makespan (the total length of the schedule for processing all the jobs).
This generator implements a variant of job-shop scheduling with the
additional assumption that every job makes use of every machine.
E. Taillard
provides benchmark instances compatible with this generator.
Changed in version 0.6.13: From version 0.4.1 to 0.6.12, the model generated used integer
variables for the start times and included explicit non-overlap
constraints between each pair of jobs on the machines.
Now the model uses a list variable for the global ordering of all tasks
and greedily constructs a feasible ordering from which the start times
are determined.
Changed in version 0.4.1: Prior to version 0.4.1, the model generated was based on one proposed by
Now the model uses the more natural formulation where the only decision
variables are the task start times, but with disjunctive non-overlapping
constraints between each pair of jobs on the machines.
Note
There are many ways to model job-shop scheduling. The model returned
by this function may or may not give the best performance for your
problem.
Parameters:
times – Processing times as an \(n\) jobs by \(m\) machines
array-like where times[n,m] is the processing time of job
\(n\) on machine \(m\).
machines – Machine order as an \(n\) jobs by \(m\) machines
array-like where machines[n,:] is the order of machines that
job \(n\) is processed on.
upper_bound – Upper bound on the makespan. If not given, defaults to
times.sum(). Note that if upper_bound is too small the
model may be infeasible.
Returns:
A model encoding the job-shop scheduling problem. The model includes
three additional methods added to it:
model.get_global_task_ordering(state_index:int): Given an
index of a state on the model, returns an array corresponding to
the global ordering of all tasks where the global task index for
the \(j\) th task of the \(i\) th job is given by \(n * i + j\).
model.get_start_times(state_index:int): Given an
index of a state on the model, returns an \(n\) by \(m\) array of
start times of each task of each job.
model.get_end_times(state_index:int): Given an
index of a state on the model, returns an \(n\) by \(m\) array of
end times of each task of each job.
Notes
The model formulation has a single
ListVariable decision variable of size
\(n \times m\) (total number of tasks), and consists of two main parts:
One to derive a global task ordering that respects the task-ordering
requirement of each job, and another to build a feasible schedule based on
that global ordering.
The first part is achieved by taking the list decision variable output, and
using \(m\)AccumulateZip
nodes nodes to select and then reorder the tasks of each job.
The second part is achieved by iterating through the tasks in the global
ordering and placing each task at the earliest possible time it can run.
Finish times for each task, as well as the finish time for the last task
on each machine, are maintained in lists and updated with
Put nodes at each iteration.
Finally, the makespan is equal to the maximum value of the finish-times
array.
Examples
This example creates a model for a job-shop-scheduling problem
with three jobs on three machines. For example, the first job
requires processing for 2 time units on the first machine, then 1 time
unit on the second machine, then 3 time units on the third machine.
In the global task ordering, the index for the \(j\) th task for the
\(i\) th job is equal to \(n*i + j\). An example solution for the final
global task ordering might be:
\[[0, 3, 4, 6, 1, 2, 7, 5, 8],\]
meaning that the first task is the first job on the first machine, the
next task is the second job on the third machine, the next task is the
second job on the first machine, etc. The model constructs a schedule
based on when the next task is available to run. The goal of the solver
is to determine a global ordering of tasks whose corresponding schedule
minimizes the makespan. The makespan (objective value) is 7, as shown in
the following code.
The iter_decisions() method
obtains the decision variables of the generated model.
>>> task_ordering=next(model.iter_decisions())
This gives the initial global task ordering from which the feasible
final global task ordering is constructed.
To test the solution above, set the corresponding initial global task
ordering in the model as the state of the decision variable. Skip
these next lines if you have submitted your model to the
Leaphybrid
nonlinear solver.
The
knapsack problem
is, for a given set of items, each with a weight and a value, to determine
which items to include in the collection so that the total weight is less
than or equal to a given limit and the total value is as large as possible.
Parameters:
values – Value per item as a 1D array-like (row vector or Python list).
Length of values must be equal to the length of weights.
Values can be any non-negative number.
weights – Weight per item as a 1D array-like (row vector or Python list).
Weights can be any non-negative number.
capacity – Maximum capacity of the knapsack. Must be a positive number.
Returns:
A model encoding the knapsack problem.
Notes
The model generated uses a
SetVariable class as the decision
variable being optimized, with permutations of the subsets of this
set representing possible items included in the knapsack.
Examples
This example creates a model for a knapsack problem
with four items.
An example feasible solution might be \([1, 2]\), meaning the
knapsack should include the second and fourth items. The objective value
for this solution is \(-1(20 + 40) = -60\), as shown in
the following code.
The iter_decisions() method
obtains the decision variables of the generated model.
>>> items=next(model.iter_decisions())
To test the solution above, set it in the model as the state of the
decision variable. Skip these next lines if you have submitted your
model to the Leaphybrid
nonlinear solver.
Here, the number of states
(size()) is set to 1 for the
constructed solution so a single value of the
objective property is printed.
>>> withmodel.lock():... foriinrange(model.states.size()):... print((f"Items in solution #{i} are {items.state(i)} with value "... f"{-model.objective.state(i)}"))Items in solution #0 are [1. 3.] with value 60.0
This example solves a
knapsack problem
(see also the knapsack() function) where weights are known but
values (prices) for these items are noisy observations.
importitertoolsimportnumpyasnpfromdwave.optimizationimportModelfromdwave.optimization.generatorsimportpredictfromsklearn.neural_networkimportMLPRegressor# The weights are known exactlyweights=np.asarray([12,1,1,2,4])# But the values, rather than being known directly, are given only# through noisy observationsdefobservations():secret_values=np.asarray([4,2,1,2,10])rng=np.random.default_rng(42)X=rng.integers(low=0,high=2,size=(20,5))y=X@secret_values+rng.normal(scale=.5,size=20)returnX,yX,y=observations()# You can now fit a multi-layer perceptron estimator to these observations. The# estimator, given a collection of purchases, estimates the values of the itemsregr=MLPRegressor(max_iter=2000).fit(X,y)# Now you can use that estimator to construct a knapsack problemmodel=Model()items=model.binary(shape=(1,5))model.minimize(-predict(regr,items))model.add_constraint(items@weights<=15)# Finally, you can solve exactly by trying all possible solutions, and check# that the solution is the correct onemodel.lock()model.states.resize(1)best_value=float("inf")best_state=Noneforstateinitertools.product((0,1),repeat=5):items.set_state(0,state)ifmodel.feasible()andmodel.objective.state()<best_value:best_value=model.objective.state()best_state=items.state()assertnp.array_equal(best_state,[[0,1,1,1,1]])
Generate a model encoding a quadratic assignment problem.
The
quadratic assignment
is, for a given list of facilities, the distances between them, and the flow
between each pair of facilities, to minimize the sum of the products of
distances and flows.
Parameters:
distance_matrix – Distances as an array-like, where distance_matrix[n,m] is
the distance between location \(n\) and \(m\). Represents
the (known and constant) distances between every possible pair of
facility locations: in real-world problems, such a matrix can be
generated from an application with access to an online map.
flow_matrix – Flows as an array-like, where flow_matrix[n,m] is the flow
between facilities \(n\) and \(m\). Represents the (known
and constant) flow between every possible pair of facilities.
Returns:
A model encoding the quadratic-assignment problem.
Notes
The model generated uses a
ListVariable class as the decision
variable being optimized, with permutations of the values of this
list representing assignments of facilities to locations.
Examples
This example creates a model for a quadratic-assignment problem
that has three facilites to place in three locations.
An example feasible solution might be \([2, 1, 0]\), meaning that
facility two should be on site zero, facility one should be on site one,
and facility zero should be on site two.[1] The objective value
for this solution is \(37\), as shown in
the following code.
The iter_decisions() method
obtains the decision variables of the generated model.
>>> locations=next(model.iter_decisions())
To test the solution above, set it in the model as the state of the
decision variable. Skip these next lines if you have submitted your
model to the Leaphybrid
nonlinear solver.
Here, the number of states
(size()) is set to 1 for the
constructed solution so a single value of the
objective property is printed.
>>> withmodel.lock():... foriinrange(model.states.size()):... print((f"Locations for solution #{i} are {locations.state(i)} with objective "... f"value of {model.objective.state(i)}"))Locations for solution #0 are [2. 1. 0.] with objective value of 37.0
This solution is shown in the figure below.
Fig. 256 Visualization of the solution. The shortest distance between pairs,
of 2 between facilities 1 and 2, has the greatest total flow of
\(1+4=5\), the longest distance between pairs, of 5 between
facilities 0 and 1, has the least total flow of \(1+2=3\), while
the intermediate distance of 3 has an intermediate total flow of
\(1+3=4\).#
Generate a model encoding a traveling-salesperson problem.
The
traveling salesperson
is, for a given list of cities and distances between each pair of cities,
to find the shortest possible route that visits each city exactly once and
returns to the city of origin.
Parameters:
distance_matrix – Distances as an array-like, where distance_matrix[n,m] is
the distance between city \(n\) and \(m\). Represents the
(known and constant) distances between every possible pair of
cities: In real-world problems, such a matrix can be generated from
an application with access to an online map. Such matrices may be
asymmetric if the direction of travel matters, such as when
different routes are used depending on direction.
Returns:
A model encoding the traveling-salesperson problem.
Notes
The model generated uses a
ListVariable class as the decision
variable being optimized, with permutations of this ordered list
representing possible itineraries through the required cities.[2]
Examples
This example creates a model for a traveling-salesperson problem
that visits three cities, where the distance depends on the direction of
travel.
Example solutions might be \([0, 1, 2]\) and \([2, 1, 0]\),
the first solution meaning that the salesperson visits city 0 then city
1 then city 2 while the second solution reverses that order. The
objective value for the first solution is \(9\) and for the second
\(3\), as shown in the following code.[3]
The iter_decisions() method
obtains the decision variables of the generated model.
>>> itinerary=next(model.iter_decisions())
To test the solution above, set it in the model as the state of the
decision variable. Skip these next lines if you have submitted your
model to the Leaphybrid
nonlinear solver.
Here, the number of states
(size()) is set to 2 for the
constructed solutions so two values of the
objective property are printed.
>>> withmodel.lock():... foriinrange(model.states.size()):... print((f"Itinerary #{i} is {itinerary.state(i)} with objective "... f"value of {model.objective.state(i)}"))Itinerary #0 is [2. 1. 0.] with objective value of 3.0Itinerary #1 is [0. 1. 2.] with objective value of 9.0