Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiling without results #52

Merged
merged 25 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
efecf37
Apply suggestions from code review
MatteoRobbiati May 31, 2024
2fd90bf
fix: rm useless line
MatteoRobbiati May 31, 2024
f91c7c4
fix: rm backend setting from build_circuit
MatteoRobbiati May 31, 2024
433ff9f
Merge pull request #39 from qiboteam/sgd_shots
MatteoRobbiati Jun 1, 2024
5c47094
results: rm very old results from main
MatteoRobbiati Jun 1, 2024
9207348
fix: Remove results
andrea-pasquale Jun 24, 2024
850e1dc
Merge branch 'main' into compiling_no_results
andrea-pasquale Jun 24, 2024
dc380ab
Merge branch 'compiling_XXZ' into compiling_no_results
andrea-pasquale Jun 24, 2024
e4a0d77
Merge branch 'compiling_XXZ' into compiling_no_results
andrea-pasquale Jun 24, 2024
bf2cdc6
feat: Example of python script
andrea-pasquale Jun 24, 2024
faed97e
feat: Trying to clean up
andrea-pasquale Jun 25, 2024
dfcfdc9
feat: Script working with Matteo's data (for sgd)
andrea-pasquale Jun 25, 2024
e38d37a
feat: Store b list
andrea-pasquale Jun 25, 2024
4f7d483
refactor: Start refactoring (not working)
andrea-pasquale Jun 25, 2024
a4d83d8
cleanup: Clean up the code
andrea-pasquale Jun 25, 2024
72ff0c3
fix: Make dbr for argparse simpler
andrea-pasquale Jun 26, 2024
38fbbe6
fix: Minor fixes
andrea-pasquale Jun 26, 2024
1df73d2
feat: Store boosting results in separate folder
andrea-pasquale Jun 26, 2024
61568c9
feat: add optimizer options and shellscript
MatteoRobbiati Jun 26, 2024
7fae4d0
feat: shellscript to run compiling.py
MatteoRobbiati Jun 26, 2024
23bf157
fix: dumping results after GCI action and pretty logs
MatteoRobbiati Jun 26, 2024
6687994
fix: rm useless file
MatteoRobbiati Jun 26, 2024
688cae3
Update compiling.py
MatteoRobbiati Jun 26, 2024
e108ee4
Merge pull request #56 from qiboteam/opts
andrea-pasquale Jun 26, 2024
ed6d4b4
Merge pull request #55 from qiboteam/refactor
andrea-pasquale Jun 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Binary file removed bp_tests/Powell_11q_20l_1/dbi_d_matrices.npz
Binary file not shown.
Binary file removed bp_tests/Powell_11q_20l_1/dbi_energies.npz
Binary file not shown.
Binary file removed bp_tests/Powell_11q_20l_1/dbi_fluctuations.npz
Binary file not shown.
Binary file removed bp_tests/Powell_11q_20l_1/dbi_steps.npz
Binary file not shown.
Binary file removed bp_tests/Powell_11q_20l_1/energies.npz
Binary file not shown.
Binary file removed bp_tests/Powell_11q_20l_1/fluctuations.npz
Binary file not shown.
Binary file removed bp_tests/Powell_11q_20l_1/gradients.npz
Binary file not shown.
Binary file removed bp_tests/Powell_11q_20l_1/grads_Grads history.pdf
Binary file not shown.
Binary file removed bp_tests/Powell_11q_20l_1/loss_Energy history.pdf
Binary file not shown.
24 changes: 0 additions & 24 deletions bp_tests/Powell_11q_20l_1/optimization_results.json

This file was deleted.

Binary file removed bp_tests/Powell_11q_20l_1/parameters_history.npy
Binary file not shown.
10 changes: 10 additions & 0 deletions compile.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash
#SBATCH --job-name=boost
#SBATCH --output=boost.log

OPTIMIZATION_METHOD="cma"
OPTIMIZATION_CONFIG="{ \"maxiter\": 2}"

python3 compiling.py --backend numpy --path "./results/XXZ_5seeds/sgd_10q_6l_27/" \
--epoch 500 --steps 2 --optimization_method $OPTIMIZATION_METHOD \
--optimization_config "$OPTIMIZATION_CONFIG"
248 changes: 248 additions & 0 deletions compiling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
import argparse
import json
import logging
import pathlib
import time
from copy import deepcopy

import numpy as np
import qibo

qibo.set_backend("numpy")
from qibo import hamiltonians
from qibo.backends import construct_backend
from qibo.quantum_info.metrics import fidelity

from boostvqe.ansatze import VQE, build_circuit
from boostvqe.models.dbi.double_bracket_evolution_oracles import (
FrameShiftedEvolutionOracle,
MagneticFieldEvolutionOracle,
XXZ_EvolutionOracle,
)
from boostvqe.models.dbi.group_commutator_iteration_transpiler import (
DoubleBracketRotationType,
GroupCommutatorIterationWithEvolutionOracles,
)
from boostvqe.utils import (
OPTIMIZATION_FILE,
PARAMS_FILE,
build_circuit,
optimize_D,
select_recursion_step_gd_circuit,
)

logging.basicConfig(level=logging.INFO)


def dump_config(config: dict, path):
config["path"] = config["path"]
config["db_rotation"] = config["db_rotation"].value
(path / "config.json").write_text(json.dumps(config, indent=4))


def main(args):
"""VQE training."""
path = pathlib.Path(args.path)
dump_path = (
path
/ f"{args.db_rotation.name}_{args.optimization_method}_{args.epoch}e_{args.steps}s"
)
dump_path.mkdir(parents=True, exist_ok=True)

config = json.loads((path / OPTIMIZATION_FILE).read_text())
dump_config(deepcopy(vars(args)), path=dump_path)

if args.optimization_config is None:
opt_options = {}
else:
opt_options = json.loads(args.optimization_config)

try:
params = np.load(path / f"parameters/params_ite{args.epoch}.npy")
except FileNotFoundError:
params = np.array(
np.load(path / PARAMS_FILE, allow_pickle=True).tolist()[0][args.epoch]
)

nqubits = config["nqubits"]
nlayers = config["nlayers"]
vqe_backend = construct_backend(backend=config["backend"])
# TODO: remove delta hardcoded
hamiltonian = getattr(hamiltonians, config["hamiltonian"])(
nqubits=nqubits, delta=0.5, backend=vqe_backend
)
vqe = VQE(
build_circuit(
nqubits=nqubits,
nlayers=nlayers,
),
hamiltonian=hamiltonian,
)
vqe.circuit.set_parameters(params)

base_oracle = XXZ_EvolutionOracle.from_nqubits(
nqubits=nqubits, delta=0.5, steps=args.steps, order=args.order
)
oracle = FrameShiftedEvolutionOracle.from_evolution_oracle(
before_circuit=vqe.circuit.invert(),
after_circuit=vqe.circuit,
base_evolution_oracle=base_oracle,
)

gci = GroupCommutatorIterationWithEvolutionOracles(
oracle,
args.db_rotation,
)

# TODO: remove hardcoded magnetic field
eo_d = MagneticFieldEvolutionOracle.from_b(
[4 - np.sin(x / 3) for x in range(nqubits)]
)
gci.eo_d = eo_d
print(
f"The gci mode is {gci.double_bracket_rotation_type} rotation with {eo_d.__class__.__name__} as the oracle.\n"
)
metadata = {}

this_report = report(vqe, hamiltonian, gci)
metadata[0] = this_report

for gci_step_nmb in range(args.steps):
logging.info(
"\n################################################################################\n"
+ f"Optimizing GCI step {gci_step_nmb+1} with optimizer {args.optimization_method}"
+ "\n################################################################################\n"
)
it = time.time()
if args.optimization_method == "sgd":
_, best_s, _, eo_d = select_recursion_step_gd_circuit(
gci,
mode_dbr_list=[args.db_rotation],
step_grid=np.linspace(1e-5, 2e-2, 30),
lr_range=(1e-3, 1),
nmb_gd_epochs=opt_options["gd_epochs"],
threshold=1e-4,
max_eval_gd=30,
please_be_visual=False,
save_path="gci_step",
)

else:
if gci_step_nmb == 0:
p0 = [0.01]
p0.extend([4 - np.sin(x / 3) for x in range(nqubits)])
else:
p0 = [best_s]
p0.extend(best_b)
optimized_params = optimize_D(
params=p0,
gci=gci,
method=args.optimization_method,
**opt_options,
)
best_s = optimized_params[0]
best_b = optimized_params[1:]
eo_d = MagneticFieldEvolutionOracle.from_b(best_b)

step_data = dict(
best_s=best_s,
eo_d_name=eo_d.__class__.__name__,
eo_d_params=eo_d.params,
)
logging.info(f"Total optimization time required: {time.time() - it} seconds")
gci.mode_double_bracket_rotation = args.db_rotation
gci.eo_d = eo_d
gci(best_s)

this_report = report(vqe, hamiltonian, gci)
print_report(this_report)
metadata[gci_step_nmb + 1] = this_report | step_data

(dump_path / "boosting_data.json").write_text(json.dumps(metadata, indent=4))


def report(vqe, hamiltonian, gci):
energies = hamiltonian.eigenvalues()
ground_state_energy = float(energies[0])
vqe_energy = float(hamiltonian.expectation(vqe.circuit().state()))
gci_loss = float(gci.loss())
gap = float(energies[1] - energies[0])

return (
dict(
nqubits=hamiltonian.nqubits,
gci_loss=float(gci_loss),
vqe_energy=float(vqe_energy),
target_energy=ground_state_energy,
diff_vqe_target=vqe_energy - ground_state_energy,
diff_gci_target=gci_loss - ground_state_energy,
gap=gap,
diff_vqe_target_perc=abs(vqe_energy - ground_state_energy)
/ abs(ground_state_energy)
* 100,
diff_gci_target_perc=abs(gci_loss - ground_state_energy)
/ abs(ground_state_energy)
* 100,
fidelity_witness_vqe=1 - (vqe_energy - ground_state_energy) / gap,
fidelity_witness_gci=1 - (gci_loss - ground_state_energy) / gap,
fidelity_vqe=fidelity(vqe.circuit().state(), hamiltonian.ground_state()),
fidelity_gci=fidelity(
gci.get_composed_circuit()().state(), hamiltonian.ground_state()
),
)
| gci.get_gate_count_dict()
)


def print_report(report: dict):
print(
f"\
The target energy is {report['target_energy']}\n\
The VQE energy is {report['vqe_energy']} \n\
The DBQA energy is {report['gci_loss']}. \n\
The difference is for VQE is {report['diff_vqe_target']} \n\
and for the DBQA {report['diff_gci_target']} \n\
which can be compared to the spectral gap {report['gap']}.\n\
The relative difference is \n\
- for VQE {report['diff_vqe_target_perc']}% \n\
- for DBQA {report['diff_gci_target_perc']}%.\n\
The energetic fidelity witness of the ground state is: \n\
- for the VQE {report['fidelity_witness_vqe']} \n\
- for DBQA {report['fidelity_witness_gci']}\n\
The true fidelity is \n\
- for the VQE {report['fidelity_vqe']}\n\
- for DBQA {report['fidelity_gci']}\n\
"
)
print(
f"The boosting circuit used {report['nmb_cnot']} CNOT gates coming from compiled XXZ evolution and {report['nmb_cz']} CZ gates from VQE.\n\
For {report['nqubits']} qubits this gives n_CNOT/n_qubits = {report['nmb_cnot_relative']} and n_CZ/n_qubits = {report['nmb_cz_relative']}"
)


if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Boosting VQE with DBI.")
parser.add_argument("--backend", default="qibojit", type=str, help="Qibo backend")
parser.add_argument("--path", type=str, help="Output folder")
parser.add_argument(
"--epoch", default=-1, type=int, help="VQE epoch where DBI will be applied."
)
parser.add_argument("--steps", default=2, type=int, help="DBI steps")
parser.add_argument("--order", default=2, type=int, help="Suzuki-Trotter order")
parser.add_argument(
"--db_rotation",
type=lambda arg: DoubleBracketRotationType[arg],
choices=DoubleBracketRotationType,
default="group_commutator_reduced",
help="DB rotation type.",
)
parser.add_argument(
"--optimization_method", default="sgd", type=str, help="Optimization method"
)
parser.add_argument(
"--optimization_config",
type=str,
help="Options to customize the optimizer training.",
)
args = parser.parse_args()
main(args)
8 changes: 5 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
DBI_ENERGIES,
DBI_FLUCTUATIONS,
DBI_STEPS,
DELTA,
FLUCTUATION_FILE,
GRADS_FILE,
HAMILTONIAN_FILE,
Expand Down Expand Up @@ -66,13 +67,14 @@ def main(args):
ham = getattr(hamiltonians, args.hamiltonian)(nqubits=args.nqubits)
target_energy = np.real(np.min(np.asarray(ham.eigenvalues())))
circ0 = build_circuit(
nqubits=args.nqubits, nlayers=args.nlayers, backend=args.backend
nqubits=args.nqubits,
nlayers=args.nlayers,
)
circ = circ0.copy(deep=True)
backend = ham.backend
zero_state = backend.zero_state(args.nqubits)

loss = partial(vqe_loss, delta=0.5, nshots=args.nshots)
loss = partial(vqe_loss, delta=DELTA, nshots=args.nshots)

# fix numpy seed to ensure replicability of the experiment
np.random.seed(int(args.seed))
Expand Down Expand Up @@ -174,7 +176,7 @@ def main(args):
circ.set_parameters(initial_parameters)

# reduce the learning rate after DBI has been applied
if "learning_rate" in opt_options.keys():
if "learning_rate" in opt_options:
opt_options["learning_rate"] *= args.decay_rate_lr

best_loss = min(np.min(array) for array in loss_history.values())
Expand Down
Loading