Appearance
Access D-Wave Leap in a PlanQK Service
This tutorial shows how to access D-Wave Annealers at D-Wave Leap from within a PlanQK Service. As an example, the code will generate a random QUBO problem and submits it, depending on input parameter, either to the simulated annealing sampler or D-Wave Leap's hybrid sampler.
Bootstrap Project
- Install the PlanQK CLI.
- Create a new project using
planqk init
and select thePlanQK Starter
template. - Open the project in your IDE of choice, e.g., VSCode.
Create Python Environment
Add the D-Wave Ocean SDK as a dependency to your project by adding dwave-ocean-sdk
to the requirements.txt
file in the root folder.
You can now set up a Python environment using Conda:
bash
conda env create -f environment.yml
conda activate <environment name>
Conda and the environment.yml
file are used by the PlanQK Platform at runtime. However, if you do not have Conda installed on your local computer, you are also able to initialize a Python virtual environment using the tooling of your choice, e.g., pyenv
or venv
.
You are now able to run the Python src
folder as module from your console:
bash
python3 -m src
Extend Project
Open the program.py
in your IDE. The run()
method is the main handler function and the entry point for your program. The method takes two arguments: (1) a data
dictionary and (2) a params
dictionary holding the input submitted by the user. PlanQK translates the Service API body/payload in the form of { "data": { <data> }, "params": { <params> } }
into these parameters.
It is also important that the run()
method returns a JSON serializable Response
object. The template makes use of the classes ResultResponse
and ErrorResponse
. It's recommended that you use these classes as well.
Next, remove the whole code from within the run()
method.
Add some required import statements:
python
import dimod
import numpy as np
from dwave.samplers import SimulatedAnnealingSampler
from dwave.system import LeapHybridSampler
Add the following code to the run()
method:
python
use_simulator = params.get('use_simulator', True)
if use_simulator:
sampler = SimulatedAnnealingSampler()
else:
sampler = LeapHybridSampler(solver={"category": "hybrid"})
bqm = dimod.generators.ran_r(1, 5)
sample_set = sampler.sample(bqm)
sample = sample_set.lowest()
sample_result = next(sample.data(fields={"sample", "energy"}))
The code first instantiates a D-Wave sampler object (either SimulatedAnnealingSampler
or LeapHybridSampler
depending on the input parameter use_simulator
). It then creates a random QUBO problem (dimod.generators.ran_r(1, 5)
) and executes the problem by calling the sample()
method of the sampler. For the sake of this demo, we select afterwards the solution with the lowest energy and extract the result data.
Finally, return some result:
python
result = {
"solution": {str(key): int(val) for key, val in sample_result.sample.items()}
}
metadata = {
"energy": sample_result.energy
}
return ResultResponse(metadata=metadata, result=result)
Source Code (program.py)
The full project can be found in our GitLab sample repository.
python
import time
from typing import Dict, Any, Union
import dimod
import numpy as np
from dwave.samplers import SimulatedAnnealingSampler
from dwave.system import LeapHybridSampler
from loguru import logger
from .libs.return_objects import ResultResponse, ErrorResponse
def run(data: Dict[str, Any] = None, params: Dict[str, Any] = None) -> Union[ResultResponse, ErrorResponse]:
use_simulator = params.get('use_simulator', True)
if use_simulator:
sampler = SimulatedAnnealingSampler()
else:
sampler = LeapHybridSampler(solver={"category": "hybrid"})
logger.debug(f"Using sampler: {sampler}")
bqm = dimod.generators.ran_r(1, 5)
sample_set = sampler.sample(bqm)
sample = sample_set.lowest()
sample_result = next(sample.data(fields={"sample", "energy"}))
result = {
"solution": {str(key): int(val) for key, val in sample_result.sample.items()}
}
metadata = {
"energy": sample_result.energy,
}
return ResultResponse(metadata=metadata, result=result)
Run the Project Locally
Run the program using python3 -m src
.
The output should be similar to the following:
shell
{"result": {"solution": {"0": -1, "1": -1, "2": -1, "3": 1, "4": -1}}, "metadata": {"energy": -6.0}}
This has run the program using the SimulatedAnnealingSampler
sampler.
To run the program using the LeapHybridSampler
sampler, add the following JSON snippet to ./input/params.json
:
json
{ "use_simulator": false }
The project, or the __main__.py
respectively, uses the data.json
and the params.json
as input for the run()
when executed locally.
If you run python3 -m src
again, the program will now fail with the error API token not defined
. This means the program code does not contain any authentication credentials to successfully execute the program against D-Wave Leap.
To overcome this issue you can expose the environment variable DWAVE_API_TOKEN
with your own D-Wave Leap access token. For example, run the program like DWAVE_API_TOKEN=PQK-f0d9e... python3 -m src
.
The next section shows how to create and run a PlanQK Service using the code you just have written.
Create a PlanQK Service
We use the PlanQK CLI to create a new service in your personal PlanQK account.
Login with the PlanQK CLI:
shell
planqk login -t <your personal access token>
Create the service:
shell
planqk up
After a while, the console should print something similar like this:
Pushing Image (2/2)... Service created 🚀
Congratulations. You have successfully created a PlanQK Service.
Before you can execute the service, a few more steps are necessary:
- Add your D-Wave Leap API token in the Provider Access Tokens settings of your account.
- On the PlanQK service overview page, open your service and go to the Runtime Configuration (
Edit Service > Runtime Configuration
). Activate the optionAdd secrets to runtime environment
. This option lets PlanQK inject your D-Wave Leap API token to the execution runtime. The value is made available through the environment variableDWAVE_API_TOKEN
. The D-Wave Ocean SDK automatically uses this variable, e.g., when working with aLeapHybridSampler
sampler object.
Run your PlanQK Service
Using the PlanQK CLI, you can quickly run a Service Job:
shell
planqk run
The run
command uses the data.json
and params.json
file as input for the job. You may adjust the values accordingly.
Alternatively, you could have created a Service Job through the PlanQK UI. More information about PlanQK Jobs and how to use them can be found in our documentation.
Furthermore, you could also publish your service for internal use and read on how to use the service utilizing PlanQK Applications. Just follow the steps in the Using a Service section in our documentation.