# 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.

`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: