Skip to main content

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 of samples 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.

optimizer = StrangeworksOptimizer(model=model, solver=solver, options=options)
sw_job = optimizer.run()

The job slug is a unique identifier for the job:

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:

optimization_job = optimizer.download_input_file(sw_job.slug)

Status

You can see check progress on the portal as well as from the SDK:

print(f"Job status: {optimizer.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.

results = optimizer.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:

results = optimizer.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:

  1. D-Wave QUBO Guide
  2. Quantum Approximate Optimization Algorithm
  3. List of QUBO Formulations