Usage
Strangeworks Optimization
This library provided by Strangeworks interacts with various optimization backends. It abstracts the differences between them, allowing users to execute jobs with ease.
StrangeworksOptimizer
Initialized by a problem model
, a solver
backend, and parameter options
.
Model: This is the problem you want to solve. It is represented as a QUBO, Ising, or other optimization problem such as MPS, CQM or DQM.
Solver: These are backend providers. Strangeworks provides a unified interface to interact with them, but each has its own unique characteristics and advantages. D-Wave, Gurobi, Quantagonia, etc.
Options: The solver
options
are parameters that are specific to the solver. For example, the number ofsamples
to take when solving the problem. See the Optimization Providers page for the required backend for more details.
Example
Here is an example of how to use the Strangeworks Optimizer to run a QUBO problem.
from strangeworks_optimization import StrangeworksOptimizer
Model
For all available models see here.
For this example we will use dimod
to create a simple QUBO problem. The QUBO problem is defined by linear and quadratic terms. The linear terms are a dictionary where the keys are the variables and the values are the linear coefficients. The quadratic terms are a dictionary where the keys are the pairs of variables and the values are the quadratic coefficients. The BinaryQuadraticModel
class is used to create the QUBO problem.
from dimod import BinaryQuadraticModel
linear = {1: -2, 2: -2, 3: -3, 4: -3, 5: -2}
quadratic = {(1, 2): 2, (1, 3): 2, (2, 4): 2, (3, 4): 2, (3, 5): 2, (4, 5): 2}
model = BinaryQuadraticModel(linear, quadratic, "BINARY")
Solver
To see all available solvers and backends see Backends.
We will use the dwave.Advantage_system6.4
solver to solve the QUBO problem.
Notice we place the provider name before the backend name to specify the full solver. For example, dwave.Advantage_system6.4
is a D-Wave solver provided by the dwave
provider.
solver = "dwave.Advantage_system6.4"
Options
Each sampler has its own Parameter Model available for import from strangeworks_optimization_models.parameter_models
. See the Optimization Providers section for more details:
from strangeworks_optimization_models.parameter_models import DwaveSamplerParameterModel
options = DwaveSamplerParameterModel(
num_reads=100,
chain_strength=50
)
The Optimization Providers section contains details of the Parameter Model and options for your solver.
Run
The StrangeworksOptimizer
class uses the run()
method to execute the job with model
, solver
, and options
as arguments.
so = StrangeworksOptimizer(
model=model,
solver=solver,
options=options
)
sw_job = so.run()
The slug is a unique identifier. You can use it to fetch the job later:
print(f"Job slug: {sw_job.slug}")
Fetching a Run
If you want to fetch a previously submitted run for resubmission or to inspect the contents, you can use the download_input_file
method to recreate the optimizer used to run the job:
so = StrangeworksOptimizer()
optimization_job = so.download_input_file(sw_job.slug)
Status
You can see check progress on the portal as well as from the SDK:
so = StrangeworksOptimizer()
print(f"Job status: {so.status(sw_job.slug)}")
The statuses include:
QUEUED
: The job is waiting to be executed.CANCELLED
: On some systems it is possible to cancel jobs.RUNNING
: The job is currently being executed.COMPLETED
: The job has been executed and the results are available.FAILED
: The job has failed to execute.
💡 Failed Jobs:
If the job status comes back as failed you can view the job page in the portal or use the Strangeworks SDK to retrieve the errors:
import strangeworks as sw
sw.get_error_messages(sw_job.slug)
Results
We made the design decision to convert all solver solutions to the dimod.sampleset format, see here for detailed documentation. This is so that results from different solvers can be easily analysed/benchmarked together without too much extra work from the user.
When the job is completed you can retrieve the solution.
so = StrangeworksOptimizer()
results = so.results(sw_job.slug)
print(f"Best solution:\n{results.solution.first}")
This will print the best most optimal solution. But there are a variety of ways to extract the full information, the one to use depends on how you plan to use it. You can print the samples:
for sample in results.solution.samples():
print(sample)
Or you can use records to get the results in standard python numpy.ndarray
format:
sample_ndarray = results.solution.record.sample
energy_ndarray = results.solution.record.energy
Also note that, you can access the raw results in the original format for each solver with this code:
so = StrangeworksOptimizer()
results = so.results(sw_job.slug)
results.solution_options["raw_results"]
🥳 Result! You have successfully used the Strangeworks Optimization Service to solve a QUBO problem.
😅 Something went wrong? Find us in Slack!
Further Reading
Expand your knowledge on QUBO and quantum optimization through these resources: