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

Ac/dta2 270 implement pauli tracker #150

Merged
merged 55 commits into from
May 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
876e726
fix: save before help from PJ
AthenaCaesura Jan 12, 2024
31319f0
fix: save before help from PJ (again)
AthenaCaesura Jan 12, 2024
bc339aa
Moving ruby slippers file into folder
pediejo Jan 12, 2024
3e11a74
Replacing icmop with orquestra circuits
pediejo Jan 12, 2024
3b0cb45
Making julia functions compatible with orquestra circuit input and ad…
pediejo Jan 12, 2024
ea5e140
fix: merge conflicts
AthenaCaesura Jan 17, 2024
c33d83e
fix: rbs with pauli tracker works
AthenaCaesura Jan 17, 2024
edb9617
fix: pauli tracker
AthenaCaesura Jan 18, 2024
af897a2
feat: commit before breaking rbs
AthenaCaesura Jan 18, 2024
f81fa19
fix: old rbs tests
AthenaCaesura Jan 29, 2024
f821dfc
fix: merge conflicts
AthenaCaesura Jan 29, 2024
8a25be1
feat: added sdk parallelization
AthenaCaesura Feb 2, 2024
5e37fd1
feat: faster temporal DAG creation
AthenaCaesura Feb 2, 2024
0384a29
fix: incorrect task imports
AthenaCaesura Feb 2, 2024
fe59e35
fix: move wf definition
AthenaCaesura Feb 2, 2024
2dbe63b
fix: move wf definition again
AthenaCaesura Feb 3, 2024
cc1d9ff
feat: slow space optimal
AthenaCaesura Feb 3, 2024
7e9eb55
feat: faster kahns algo
AthenaCaesura Feb 3, 2024
05ca032
fix: stuff
AthenaCaesura Feb 8, 2024
50b8330
fix: move tasks out of transformer
AthenaCaesura Feb 8, 2024
6ac8988
feat: parallelized pipeline
AthenaCaesura Feb 8, 2024
7d86f34
feat: rigetti instances
AthenaCaesura Feb 8, 2024
0cd9ce1
fix: remove graph production method as input
AthenaCaesura Feb 8, 2024
bdd060a
fix: problems
AthenaCaesura Feb 9, 2024
e72afff
feat: better low qubit counts
AthenaCaesura Feb 13, 2024
c35dbbd
fix: orquestra integration
AthenaCaesura Feb 15, 2024
ee8a281
fix: commit before removing unneeded sections
AthenaCaesura Feb 23, 2024
9d1800e
feat: better costing
AthenaCaesura Mar 1, 2024
92eb954
fix: updated new example to new api
AthenaCaesura Mar 4, 2024
a9ffbb7
fix: examples run
AthenaCaesura Mar 6, 2024
5cf348f
fix: some tests
AthenaCaesura Mar 16, 2024
94d5d99
fix: more tests pass
AthenaCaesura Mar 25, 2024
09771e5
fix: graph estimator tests pass
AthenaCaesura Mar 27, 2024
4c45f39
fix: sre_constants no longer fail tests
AthenaCaesura Mar 28, 2024
2a4c766
fix: all tests pass
AthenaCaesura Mar 29, 2024
b7bb881
fix: passes style
AthenaCaesura Mar 29, 2024
5c16b06
fix: merge conflicts
AthenaCaesura Mar 29, 2024
e189f2e
fix: remove union from singledispatch
AthenaCaesura Mar 29, 2024
d143f05
fix: pyright issues
AthenaCaesura Mar 29, 2024
541bf7f
fix: pyright issues
AthenaCaesura Mar 29, 2024
a4823f5
fix: tests pass
AthenaCaesura Mar 29, 2024
7e279a7
fix: line too long
AthenaCaesura Mar 29, 2024
8ddc693
fix: simplified jabalizer integration
AthenaCaesura Apr 18, 2024
eafa04c
fix: added choice to install jabalizer
AthenaCaesura Apr 18, 2024
443c798
fix: azure example
AthenaCaesura Apr 18, 2024
e7d65e9
Updating pauli tracker docstring
max-radin Apr 22, 2024
78f2513
feat: resource breakdowns
AthenaCaesura May 1, 2024
8b3561b
Merge branch 'ac/DTA2-270-implement-pauli-tracker' of https://github.…
AthenaCaesura May 1, 2024
5aec594
fix: merge conflicts
AthenaCaesura May 1, 2024
41ce14a
fix: don't use jabalizer unless installed
AthenaCaesura May 1, 2024
fa4798b
fix: added individual testing for stitching
AthenaCaesura May 2, 2024
290f868
Merge remote-tracking branch 'origin/ac/100-fermi-hubbard' into ac/DT…
AthenaCaesura May 2, 2024
5d012cd
fix: tests pass
AthenaCaesura May 15, 2024
5e6508d
feat: eliminate max independent set
AthenaCaesura May 15, 2024
5449cd9
Merge remote-tracking branch 'origin' into ac/DTA2-270-implement-paul…
AthenaCaesura May 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,6 @@ juliapkg.json

# igonore mlflow run files
*mlruns*

# ignore jabalizer files
jabalizer_temp/
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ style: flake8p mypy pyright black isort
@echo This project passes style!

test:
$(PYTHON) -m pytest -W error tests
$(PYTHON) -m pytest tests

coverage:
$(PYTHON) -m pytest -W error\
$(PYTHON) -m pytest \
--cov=src \
--cov-fail-under=$(MIN_COVERAGE) tests \
--no-cov-on-fail \
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ On some systems, the installation of PySCF can be problematic. If you're a Windo
#### Azure Quantum Resource Estimation
To run resource estimation using Azure Quantum Resource Estimation (QRE) tool, one needs to have Azure QRE package configure. See [this tutorial](https://learn.microsoft.com/en-us/azure/quantum/intro-to-resource-estimation) for more information.

#### Jabalizer
Jabalizer is an alternate graph state compilation toolchain to ruby slippers. To install Jabalizer, you will need to have the Rust programming language installed on your machine and run `pip install '.[jabalizer]'` from the top-level directory of this repository.

Jabalizer can provide drastically reduced resource counts for some circuits, but it is considerably slower than ruby slippers. It is recommended to use Jabalizer only for smaller circuits.

## Usage
See the [`examples`](examples) directory to learn more about how to use Bench-Q.

Expand Down
24 changes: 14 additions & 10 deletions benchmarks/test_get_qsp_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
import zipfile
from pathlib import Path

import openfermion
import pytest

from benchq.algorithms.time_evolution import _n_block_encodings_for_time_evolution
from benchq.problem_embeddings import get_qsp_program
from benchq.conversions import get_pyliqtr_operator
from benchq.problem_embeddings.qsp import get_qsp_program
from benchq.problem_ingestion import get_hamiltonian_from_file, get_vlasov_hamiltonian
from benchq.problem_ingestion.molecular_hamiltonians import (
get_hydrogen_chain_hamiltonian_generator,
Expand All @@ -27,9 +29,10 @@ def vlasov_test_case():
failure_tolerance = 1e-3

operator = get_vlasov_hamiltonian(k, alpha, nu, N)
pyliqtr_operator = get_pyliqtr_operator(operator)

n_block_encodings = _n_block_encodings_for_time_evolution(
operator, evolution_time, failure_tolerance
pyliqtr_operator, evolution_time, failure_tolerance
)

return pytest.param(operator, n_block_encodings, id="vlasov")
Expand All @@ -40,22 +43,23 @@ def jw_test_case():
failure_tolerance = 1e-3
n_hydrogens = 2

operator = get_hydrogen_chain_hamiltonian_generator(
n_hydrogens
).get_active_space_hamiltonian()
instance = generate_hydrogen_chain_instance(n_hydrogens)
interaction_operator = instance.get_active_space_hamiltonian()
jw_operator = openfermion.jordan_wigner(interaction_operator)
pyliqtr_jw_operator = get_pyliqtr_operator(jw_operator)

n_block_encodings = _n_block_encodings_for_time_evolution(
operator, evolution_time, failure_tolerance
pyliqtr_jw_operator, evolution_time, failure_tolerance
)

return pytest.param(
operator,
pyliqtr_jw_operator,
n_block_encodings,
id=f"jw-{n_hydrogens}",
)


def fast_load_test_cases():
def fast_load_hamiltonians():
evolution_time = 5
failure_tolerance = 1e-3
base_location = "./examples/data/"
Expand All @@ -74,7 +78,7 @@ def _load_hamiltonian(name):

return [
pytest.param(
(operator := _load_hamiltonian(name)),
(operator := get_pyliqtr_operator(_load_hamiltonian(name))),
_n_block_encodings_for_time_evolution(
operator, evolution_time, failure_tolerance
),
Expand All @@ -92,7 +96,7 @@ def _load_hamiltonian(name):
@pytest.mark.benchmark
@pytest.mark.parametrize(
"operator, n_block_encodings",
[vlasov_test_case(), jw_test_case(), *fast_load_test_cases()],
[vlasov_test_case(), jw_test_case(), *fast_load_hamiltonians()],
)
def test_get_qsp_program(benchmark, operator, n_block_encodings):
benchmark(get_qsp_program, operator, n_block_encodings)
3 changes: 2 additions & 1 deletion benchmarks/test_ruby_slippers_performance.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import pytest
from orquestra.quantum.circuits import CNOT, RX, Circuit, H, S, X, Z

from benchq.compilation import jl, pyliqtr_transpile_to_clifford_t
from benchq.compilation.circuits import pyliqtr_transpile_to_clifford_t
from benchq.compilation.graph_states import jl


@pytest.mark.parametrize(
Expand Down
12 changes: 7 additions & 5 deletions benchmarks/test_substrate_scheduler_performance.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import networkx as nx
import pytest

from benchq.resource_estimators.graph_estimators import substrate_scheduler
from benchq.compilation.graph_states.substrate_scheduler.python_substrate_scheduler import (
python_substrate_scheduler,
)


@pytest.mark.parametrize("preset", ["fast", "optimized"])
Expand All @@ -13,7 +15,7 @@ class TestSubstrateScheduler:
@pytest.mark.parametrize("size", [10, 100, 1000])
def test_substrate_scheduler_timing(self, benchmark, graph, size, preset):
graph = graph(size)
benchmark(substrate_scheduler, graph, preset)
benchmark(python_substrate_scheduler, graph, preset)

@pytest.mark.parametrize(
"graph",
Expand All @@ -24,20 +26,20 @@ def test_substrate_scheduler_timing_with_pre_mapping_optimizer(
self, benchmark, graph, size, preset
):
graph = graph(size)
benchmark(substrate_scheduler, graph, preset)
benchmark(python_substrate_scheduler, graph, preset)

@pytest.mark.parametrize("chain_size", [10, 100])
@pytest.mark.parametrize("bell_size", [10, 100])
def test_substrate_scheduler_timing_barbell_graph(
self, benchmark, chain_size, bell_size, preset
):
graph = nx.barbell_graph(chain_size, bell_size)
benchmark(substrate_scheduler, graph, preset)
benchmark(python_substrate_scheduler, graph, preset)

@pytest.mark.parametrize("size", [10, 100])
@pytest.mark.parametrize("probablity_of_edge", [0.01, 0.1])
def test_substrate_scheduler_timing_erdos_renyi(
self, benchmark, size, probablity_of_edge, preset
):
graph = nx.erdos_renyi_graph(size, probablity_of_edge, seed=123)
benchmark(substrate_scheduler, graph, preset)
benchmark(python_substrate_scheduler, graph, preset)
5 changes: 2 additions & 3 deletions examples/data/single_rotation.qasm
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
OPENQASM 2.0;
include "qelib1.inc";
qreg q[4];
h q[0];
rz(0.20103392) q[0];
qreg q[1];
rx(0.20103392) q[0];
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
import datetime
import json
import os
import typing
import warnings
from pathlib import Path
from typing import Literal

from benchq.algorithms.time_evolution import qsp_time_evolution_algorithm
from benchq.compilation import get_ruby_slippers_compiler
from benchq.compilation.graph_states.circuit_compilers import (
get_ruby_slippers_circuit_compiler,
)
from benchq.compilation.graph_states.implementation_compiler import (
get_implementation_compiler,
)
from benchq.decoder_modeling import DecoderModel
from benchq.problem_ingestion.solid_state_hamiltonians.ising import (
generate_ising_hamiltonian_on_cubic_lattice,
generate_ising_hamiltonian_on_kitaev_lattice,
generate_ising_hamiltonian_on_triangular_lattice,
)
from benchq.quantum_hardware_modeling import DETAILED_ION_TRAP_ARCHITECTURE_MODEL
from benchq.resource_estimators.footprint_estimators.openfermion_estimator import (
footprint_estimator,
)
from benchq.resource_estimators.graph_estimators import (
ExtrapolationResourceEstimator,
create_big_graph_from_subcircuits,
get_custom_extrapolated_estimate,
remove_isolated_nodes,
transpile_to_native_gates,
from benchq.quantum_hardware_modeling import (
BASIC_SC_ARCHITECTURE_MODEL,
DETAILED_ION_TRAP_ARCHITECTURE_MODEL,
)
from benchq.resource_estimators.graph_estimator import GraphResourceEstimator
from benchq.resource_estimators.openfermion_estimator import openfermion_estimator


def get_resources(lattice_type: str, size: int, decoder_data_file: str):
Expand All @@ -38,60 +35,44 @@ def get_resources(lattice_type: str, size: int, decoder_data_file: str):
else:
raise ValueError(f"Lattice type {lattice_type} not supported")

architecture_model = DETAILED_ION_TRAP_ARCHITECTURE_MODEL
architecture_model = BASIC_SC_ARCHITECTURE_MODEL

print("Getting algorithm implementation...")
evolution_time = 1
failure_tolerance = 1e-4
failure_tolerance = 1e-3
algorithm_implementation = qsp_time_evolution_algorithm(
operator, evolution_time, failure_tolerance
)

print("Setting resource estimation parameters...")
decoder_model = DecoderModel.from_csv(decoder_data_file)
my_estimator = ExtrapolationResourceEstimator(
architecture_model,
[2, 4, 6, 8, 10],
n_measurement_steps_fit_type="logarithmic",
optimization="space",
decoder_model=decoder_model,
circuit_compiler = get_ruby_slippers_circuit_compiler(
teleportation_threshold=80, optimal_dag_density=10
)

# select teleportation threshold to tune number of logical qubits
if lattice_type == "triangular":
gpm = get_ruby_slippers_compiler(teleportation_threshold=70)
elif lattice_type == "kitaev":
gpm = get_ruby_slippers_compiler(teleportation_threshold=60)
elif lattice_type == "cubic":
gpm = get_ruby_slippers_compiler(teleportation_threshold=70)
else:
raise ValueError(f"Lattice type {lattice_type} not supported")
implementation_compiler = get_implementation_compiler(
circuit_compiler, destination="single-thread"
)
estimator = GraphResourceEstimator(optimization="Space", verbose=True)

print("Estimating resources via graph state compilation...")
gsc_resources = get_custom_extrapolated_estimate(
gsc_resources = estimator.compile_and_estimate(
algorithm_implementation,
my_estimator,
transformers=[
transpile_to_native_gates,
create_big_graph_from_subcircuits(gpm),
remove_isolated_nodes,
],
)

total_t_gates = my_estimator.get_n_total_t_gates(
gsc_resources.extra.n_t_gates,
gsc_resources.extra.n_rotation_gates,
algorithm_implementation.error_budget.transpilation_failure_tolerance,
implementation_compiler,
architecture_model,
decoder_model,
)

total_t_gates = algorithm_implementation.n_t_gates_after_transpilation
hw_tolerance = algorithm_implementation.error_budget.hardware_failure_tolerance
footprint_resources = footprint_estimator(

footprint_resources = openfermion_estimator(
algorithm_implementation.program.num_data_qubits,
num_t=total_t_gates,
architecture_model=my_estimator.hw_model,
architecture_model=architecture_model,
hardware_failure_tolerance=hw_tolerance,
decoder_model=decoder_model,
)

return gsc_resources, footprint_resources


Expand Down Expand Up @@ -138,7 +119,7 @@ def main(
save_results = False
path_to_save_results = "."

utiliy_scale_problems: typing.Dict[
utility_scale_problems: typing.Dict[
Literal["triangular", "kitaev", "cubic"], int
] = {"triangular": 30, "kitaev": 22, "cubic": 10}

Expand All @@ -152,7 +133,7 @@ def main(
decoder_data,
save_results,
lattice_type,
utiliy_scale_problems[lattice_type],
utility_scale_problems[lattice_type],
path_to_save_results,
)

Expand Down
42 changes: 14 additions & 28 deletions examples/ex_1_from_qasm.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,14 @@

import os

from orquestra.integrations.qiskit.conversions import import_from_qiskit
from qiskit.circuit import QuantumCircuit

from benchq.algorithms.data_structures import AlgorithmImplementation, ErrorBudget
from benchq.problem_embeddings import get_program_from_circuit
from benchq.quantum_hardware_modeling import BASIC_SC_ARCHITECTURE_MODEL
from benchq.resource_estimators.graph_estimators import (
GraphResourceEstimator,
create_big_graph_from_subcircuits,
get_custom_resource_estimation,
synthesize_clifford_t,
transpile_to_native_gates,
from benchq.compilation.graph_states.implementation_compiler import (
get_implementation_compiler,
)
from benchq.quantum_hardware_modeling import BASIC_SC_ARCHITECTURE_MODEL
from benchq.resource_estimators.graph_estimator import GraphResourceEstimator


def main(file_name):
Expand All @@ -43,32 +38,23 @@ def main(file_name):
qiskit_circuit, error_budget, 1
)

# Here we run the resource estimation pipeline:
# Architecture model is used to define the hardware model.
architecture_model = BASIC_SC_ARCHITECTURE_MODEL

# Here we run the resource estimation pipeline.
# In this case before performing estimation we use the following transformers:
# 1. Simplify rotations – it is a simple transpilation that removes redundant
# rotations from the circuit, such as RZ(0) or RZ(2pi) and replaces RX and RY
# gates with RZs
# 2. Gate synthesis – replaces all RZ gates with Clifford+T gates
# 3. Create big graph from subcircuits – this transformer is used to create
# a graph from subcircuits. It is needed to perform resource estimation using
# the graph resource estimator. In this case we use delayed gate synthesis, as
# we have already performed gate synthesis in the previous step.
gsc_resource_estimates = get_custom_resource_estimation(
# Create the estimator object, we can optimize for "Time" or "Space"
estimator = GraphResourceEstimator(optimization="Time", verbose=True)
# Use the default compiler
compiler = get_implementation_compiler()
# Put all the pieces together to get a resource estimate
gsc_resource_estimates = estimator.compile_and_estimate(
algorithm_implementation,
estimator=GraphResourceEstimator(architecture_model),
transformers=[
transpile_to_native_gates,
synthesize_clifford_t(error_budget),
create_big_graph_from_subcircuits(),
],
compiler,
architecture_model,
)
print("Resource estimation results:")
print(gsc_resource_estimates)


if __name__ == "__main__":
current_directory = os.path.dirname(__file__)
main(current_directory + "/data/example_circuit.qasm")
main(current_directory + "/data/ghz_circuit.qasm")
Loading
Loading