# Kipu Bias Field Digitized Counterdiabatic Quantum Optimization - BFDCQO
This service implements Kipu's Bias-Field Digitized Counterdiabatic Quantum Optimization (BF-DCQO) algorithm to solve optimization problems.
It uses Kipu's technique of algorithmic compression by using counterdiabatic protocols.
This is an iterative algorithm where the output from each iteration is fed back as a bias to the input of the next iteration.

## Usage

Quantum computing can be used to find the ground state (minimum energy state) of an Ising Hamiltonian of the form
$$H = \sum_i^N h_i\sigma_i^z + \sum_i^N \sum_{j>i}^N J_{ij}\sigma_i^z\sigma_j^z$$

Many standard optimization problems from industrial use cases can be restated in Ising form. We assume that the user has already a problem in the form described above.

Our service requires you to provide
- the single body Ising coefficients $h_i$,
- and the two-body coefficients $J_{ij}$,
- additional parameters (specified below).

The input data needs to be supplied in JSON format. A full JSON input for the service has the following form:

```json
{
  "data": {
    "bf_dcqo": {
      "coefficients": {
        "(0,)": 0.05009721367530462,
        "(0, 1)": 0.1589373302733451,
        "(0, 2)": -0.1465938630044573,
        "(0, 3)": 0.1444447352374391,
        "(1,)": -0.008103805367511346,
        "(1, 2)": -0.10385855447216596,
        "(1, 3)": 0.014771937124279128,
        "(2,)": -0.5638808178837599,
        "(2, 3)": -0.1014721471152484,
        "(3,)": 0.023722798165331543
      },
      "annealing_time": 0.7,
      "trotter_steps": 2,
      "cd_mode": "CD",
      "bf_mode": "sign",
      "shots": 1024,
      "num_iterations": 4,
       "counts": None
    }
  },
  "params": {
    "backend": "azure.ionq.simulator"
  }
}
```

The `data` section contains the specification of the circuit to be constructed in the `bf_dcqo` attribute,  including the Hamiltonian coefficients, annealing time, number of Trotter steps, and the mode of operation. It also includes the parameters that configure the iterative part of the algorithm such as the type of bias and the number of iterations to be run.

The `params` section includes the parameters for the submission of the circuit to a hardware backend,
including the number of shots and the backend.

### Hamiltonian coefficients
The Hamiltonian coefficients $h_i$ and $J_{ij}$ are specified in the `coefficients` attribute, where each key
`(i,)` corresponds to the single body coefficient  $h_i$ and the `(i,j)` key corresponds to the two-body interaction coefficient $J_{ij}$. **Note that we use $0$-indexing for the coefficients.**

###  BF-DCQO Hyperparameters
#### Annealing time: `annealing_time`
The total time over which the quantum system evolves from the initial Hamiltonian to the problem Hamiltonian. It is a crucial parameter in quantum annealing and counterdiabatic quantum computing, as it determines the duration of the evolution process.
#### Trotter stteps:`trotter_steps`
The number of discrete time steps used to approximate the continuous evolution of the quantum system. This is based on the Trotter-Suzuki decomposition, which breaks down the exponential of a sum of non-commuting operators into a product of exponentials of the individual operators. More Trotter steps generally lead to a more accurate approximation of the continuous evolution but also increase the complexity of the quantum circuit.
#### Evolution Mode: `mode`
The mode determines the type of Hamiltonian evolution used in the algorithm. In the context of Counterdiabatic Quantum Computing (CQC), there are typically three modes:

- Counterdiabatic: `mode = CD`
  Only the counterdiabatic term is included in the Hamiltonian.  This mode gives you Kipu's algorithmic compression and should be used with a small annealing time $0.5 < T  < 1.5$.

- Full:  `mode = FULL`
  Both the adiabatic and counterdiabatic terms are included in the Hamiltonian.
### Number of iterations: `num_iterations`
The number of iterations the algorithm is executed. After each iteration the bias field is updated with the result of the current execution.
### Number of shots: `shots`
Number of shots (repetitions) for the simulation.
### Bias-field mode: `bf_mode`
The bias-field mode determines how the bias field is calculated from the bitstring counts which result from the previous iteration. A bias-field is applied individually to each qubit and it depends only on the measurements of its corresponding qubit in the computational basis from the previous iteration. Currently there are two modes available:

- Unsigned: `bf_mode = unsigned_anti`
  The bias-field applied to each qubit is obtained from the expectation value of the z pauli operator, which can be calculated directly from the bitstring counts of the previous iteration. This mode applies a bias-field to each qubit of the form
  $$b = -\langle \sigma^{z}_i \rangle \sigma^z_i$$

- Signed: `bf_mode = anti_signed`
  The bias-field applied to each qubit is obtained from the sign of the expectation value of the z pauli operator, which can be calculated directly from the bitstring counts of the previous iteration. This mode applies a bias-field to each qubit of the form
  $$b = - \textrm{sign}(\langle \sigma^{z}_i \rangle) \sigma^z_i$$

### Bitstring Counts: `counts`
In case a submission fails before the algorithm is finished, the user can input the bitstring counts

### Circuit submission parameters

The `params` section includes the `backend` attribute to set the hardware backend for the quantum computation.

## Results
The service submits a circuit to the hardware backend for each iteration set for the algorithm. After the last iteration is completed the service returns a JSON file, with the bitstring counts in the `counts` attribute and information of the job submission and the number of iterations completed (`job_id`, `backend_name`, `shots`, `iteration`).

- Restarting the service from the point of failure
  In case where the service fails before returning the final result, the user can start a new submission that continues the algorithm from the previous point of failure. At the point of failure, the service will return a JSON file containing the results from the last iteration that was successfully run. The result JSON file contains (`counts`,`job_id`, `backend_name`, `shots`, `iteration`), where `iteration` corresponds to the last iteration that was completed, and `counts` contains the corresponding bitstring counts.
  In order to continue the algorithm from the last iteration, the user can start a new service using the same data input as for the first submission, and adding the bitstring counts from the result JSON file into the `counts` field for the input data JSON file. Additionally, the `num_iterations` field in the input JSON file must be updated to be the remaining iterations required to complete the algorithm.


### Bitstring ordering and spin variable convention
The returned bitstrings follow the big endian convention, where the bit `x[i]` of a bitstring `x` corresponds to the spin variable (qubit) $\sigma_i^z$. The map from binary variables $x_{i}= 0,1$ to spin variables $\sigma_{i}^z=1,-1$ is $\sigma_{i}^z= 1-2x_i.$

Similarly, if a circuit is returned qubit $i$ in the circuit will correspond to the $i$-th variable in the input data.

``` json
{'backend_name': 'azure.ionq.simulator',
 'job_id': '27a9e8c9-b50a-446b-86b7-706cefd3a707',
 'counts': {'1000': 306,
  '1110': 41,
  '1011': 44,
  '1010': 13,
  '0010': 1,
  '0101': 209,
  '0110': 5,
  '0011': 5,
  '0000': 19,
  '0100': 103,
  '1111': 38,
  '1100': 68,
  '0001': 87,
  '1001': 67,
  '0111': 18},
 'shots': 1024}
```



# How to use this Service

The PlanQK Service SDK serves as your gateway to seamless interaction with the PlanQK service through Python. Follow the steps below for a smooth integration experience.

Start by installing the PlanQK Service SDK Python library with the following command:

```
pip install --upgrade planqk-service-sdk
```

Prepare the consumer key and consumer secret by subscribing to this service using an application. [Applications](https://platform.planqk.de/applications) on the PlanQK Platform hold all necessary information for secure communication with the service. Just use the _Subscribe_ button on the right and select the appropriate application.

Replace `your_consumer_key` and `your_secret_key` in the code snippet below with the credentials provided in your application:

``` python
from planqk.service.client import PlanqkServiceClient

consumer_key = "your_consumer_key"
consumer_secret = "your_consumer_secret"
service_endpoint = "https://gateway.platform.planqk.de/kipu-quantum/kipu-bias-field-digitized-counterdiabatic-quantum-optimization---bfdcqo/1.0.0"

client = PlanqkServiceClient(service_endpoint, consumer_key, consumer_secret)

# prepare your input data and parameters
data = {
    "bf_dcqo": {
      "coefficients": {
        "(0,)": 0.05009721367530462,
        "(0, 1)": 0.1589373302733451,
        "(0, 2)": -0.1465938630044573,
        "(0, 3)": 0.1444447352374391,
        "(1,)": -0.008103805367511346,
        "(1, 2)": -0.10385855447216596,
        "(1, 3)": 0.014771937124279128,
        "(2,)": -0.5638808178837599,
        "(2, 3)": -0.1014721471152484,
        "(3,)": 0.023722798165331543
      },
      "annealing_time": 0.7,
      "trotter_steps": 2,
      "cd_mode": "CD",
      "bf_mode": "unsigned_anti",
      "shots": 1024,
      "num_iterations": 4
    }
}
params = {
    "backend": "azure.ionq.simulator"
  }

# start the execution
job = client.start_execution(data=data, params=params)

# wait for the result
result = client.get_result(job.id)
```