# GradCoRe Implementation

## Suggested Installation

Move into the repository's directory and create a new python environment:
```bash
python -m venv .venv
```

Install the gradcore module with pip:
```bash
.venv/bin/pip install -e .
```

## Creating the training data

When comparing different optimization routines, it is important to make sure the difference in the performance is not
due to some different initialization or seeds. In order to ensure every optimization starts from the same point and uses
the same seed one can initialize different optimization schemes from the same initial points. To do so, the first step
is to create a train set using the `make-train` routine of the `gradcore` module script

Set the common

```bash
mkdir train_data
.venv/bin/python -m gradcore \
    --seed 3735928559 \
    make-train \
    train_data/train-ising-5-3-1024.h5 \
    --j-coupling -1,0,0 \
    --h-coupling 0,0,-1 \
    --n-qbits 5 \
    --n-layers 3 \
    --circuit esu2 \
    --pbc no \
    --n-readout 512 \
    --train-samples 1
```

Once the training dataset has been generated it can be loaded for initializing any optimization using the
`--train-data` option as shown in the examples below. One caveat is that the setup (couplings, qubits, layers, readout
etc.) specified for creating the training set should coincide with the parameters of the optimization.

## Running

The GradCoRe repository implements the following algorithms as baselines:

- Nakanishi-Fuji-Todo (NFT)
- Bayes-NFT (NFT using a GP)
- SubsCoRe (NFT using a GP with adaptive number of measurement shots)
- SGD
- Bayes-SGD (SGD using a GP)
- SGD-GradCoRe (our) (SGD using a derivative-GP with adaptive measurement shots):

The following algorithms use their respective author's implementations:

- [EmiCoRe](https://github.com/emicore/emicore) (NFT using a GP with adaptive measurement points)
- SGLBO (ask authors for code)

Detailed hyperparameters for reproducing the experiments of the paper can be found in the appendix in section
**E Experiment Details**.


### NFT (baseline)

```bash
.venv/bin/python -m gradcore train \
    ising-5-3-1024-nft.h5 \
    --train-data train_data/train-ising-5-3-1024.h5 \
    --j-coupling -1,0,0 \
    --h-coupling 0,0,-1 \
    --n-qbits 5 \
    --n-layers 3 \
    --circuit esu2 \
    --pbc no \
    --n-readout 512 \
    --iter-mode readout \
    --n-iter 100000 \
    --acq-params 'optim=nft,stabilize_interval=1'
```

### Bayes-NFT (baseline)

```bash
.venv/bin/python -m gradcore train \
    ising-5-3-1024-nftgp.h5 \
    --train-data train_data/train-ising-5-3-1024.h5 \
    --j-coupling -1,0,0 \
    --h-coupling 0,0,-1 \
    --n-qbits 5 \
    --n-layers 3 \
    --circuit esu2 \
    --pbc no \
    --iter-mode readout \
    --n-iter 100000 \
    --n-readout 512 \
    --kernel-params 'sigma_0=10,gamma=3' \
    --inducer 'last_slack_pivot:retain=399:slack=40' \
    --acq-params 'optim=nftgp,stabilize_interval=1'
```

### EMICoRe (baseline)

Proceed to https://github.com/emicore/emicore .
Here, we used the parameters as described in **E Experiment Details**

### SubsCoRe (baseline)

```bash
.venv/bin/python -m gradcore train \
    ising-5-3-1024-subscore.h5 \
    --train-data train_data/train-ising-5-3-1024.h5 \
    --j-coupling -1,0,0 \
    --h-coupling 0,0,-1 \
    --n-qbits 5 \
    --n-layers 3 \
    --circuit esu2 \
    --pbc no \
    --iter-mode readout \
    --n-iter 100000 \
    --kernel-params 'sigma_0=10,gamma=3' \
    --inducer 'last_slack_pivot:retain=399:slack=40' \
    --acq-params '
        optim=subscore,
        readout-strategy=center,
        corethresh-strategy=grad,
        coremetric=readout,
        coremin-scale=2048,
        corethresh=256,
        corethresh-width=40,
        corethresh-scale=1.0'
```


### SGD (baseline)

```bash
.venv/bin/python -m gradcore train \
    ising-5-3-1024-sgd.h5 \
    --train-data train_data/train-ising-5-3-1024.h5 \
    --j-coupling -1,0,0 \
    --h-coupling 0,0,-1 \
    --n-qbits 5 \
    --n-layers 3 \
    --circuit esu2 \
    --pbc no \
    --iter-mode readout \
    --n-iter 100000 \
    --n-readout 16 \
    --var-mode none \
    --acq-params '
        optim=sgd,
        gdoptim=adam,
        lr=0.05,
        shift_mode=pi2'
```

### Bayes-SGD (baseline)

```bash
.venv/bin/python -m gradcore train \
    ising-5-3-1024-sgdgp.h5 \
    --train-data train_data/train-ising-5-3-1024.h5 \
    --j-coupling -1,0,0 \
    --h-coupling 0,0,-1 \
    --n-qbits 5 \
    --n-layers 3 \
    --circuit esu2 \
    --pbc no \
    --iter-mode readout \
    --n-iter 100000 \
    --n-readout 16 \
    --kernel-params 'sigma_0=10,gamma=1' \
    --inducer 'last_slack:retain=400:slack=0' \
    --acq-params '
        optim=sgdgp,
        gdoptim=adam,
        lr=0.05,
        shift_mode=pi2'
```

### SGD-GradCoRe (our)

```bash
.venv/bin/python -m gradcore train \
    ising-5-3-1024-gradcore.h5 \
    --train-data train_data/train-ising-5-3-1024.h5 \
    --j-coupling -1,0,0 \
    --h-coupling 0,0,-1 \
    --n-qbits 5 \
    --n-layers 3 \
    --circuit esu2 \
    --pbc no \
    --iter-mode readout \
    --n-iter 100000 \
    --kernel-params 'sigma_0=10,gamma=3' \
    --inducer 'last_slack:retain=400:slack=0' \
    --acq-params '
        optim=gradcore,
        corethresh-strategy=grad,
        pnorm=2,
        corethresh=256,
        corethresh_width=40,
        coremin-scale=2048,
        corethresh-scale=1.2,
        coremetric=readout,
        lr=0.05,
        gdoptim=adam,
        readout-strategy=core,
        shift_mode=pi2'
```
