Skip to content

Commit

Permalink
Merge branch 'main' of github.com:Qiskit-Extensions/circuit-knitting-…
Browse files Browse the repository at this point in the history
…toolbox into translate-sampled-gates
  • Loading branch information
caleb-johnson committed Jun 3, 2024
2 parents 4aac71f + 67f24cb commit 41b5881
Show file tree
Hide file tree
Showing 52 changed files with 881 additions and 5,637 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ jobs:
- name: Install tox
run: |
python -m pip install --upgrade pip
pip install tox coveragepy-lcov 'coverage<7'
pip install tox coverage
- name: Run coverage
run: |
tox -e coverage
- name: Convert to lcov
run: coveragepy-lcov --output_file_path coveralls.info
run: coverage3 lcov -o coveralls.lcov
- name: Upload report to Coveralls
uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
file: coveralls.info
file: coveralls.lcov
format: lcov
13 changes: 4 additions & 9 deletions .github/workflows/test_latest_versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ jobs:
max-parallel: 4
matrix:
os: [ubuntu-latest]
python-version: ["3.9", "3.12"]
python-version: ["3.8", "3.12"]
include:
- os: macos-13
python-version: "3.8"
- os: macos-latest
python-version: "3.12"
- os: windows-latest
python-version: "3.10"
steps:
Expand All @@ -46,9 +46,4 @@ jobs:
run: |
pver=${{ matrix.python-version }}
tox -epy${pver/./} -- --run-slow
notebook_flags=""
if [ "$pver" = "3.12" ]; then
echo Skipping tutorials that require cplex
notebook_flags="${notebook_flags} --ignore=docs/circuit_cutting/cutqc/tutorials/tutorial_1_automatic_cut_finding.ipynb"
fi
tox -epy${pver/./}-notebook -- ${notebook_flags}
tox -epy${pver/./}-notebook
2 changes: 0 additions & 2 deletions .mypy.ini

This file was deleted.

15 changes: 0 additions & 15 deletions .ruff.toml

This file was deleted.

3 changes: 0 additions & 3 deletions CITATION.bib
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ @misc{circuit-knitting-toolbox
and Edwin Pednault
and C. D. Pemmaraju
and Pedro Rivero
and Seetharami Seelam
and Ibrahim Shehzad
and Dharmashankar Subramanian
and Wei Tang
and Stefan Woerner
},
title = {{Circuit Knitting Toolbox}},
Expand Down
53 changes: 6 additions & 47 deletions INSTALL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,8 @@ packages. There are three primary ways to do this:
- :ref:`Option 2`
- :ref:`Option 3`

CutQC users should consult the :ref:`Platform Support` section to determine
which installation option is appropriate for them. Users who wish to run within a
containerized environment may skip the pre-installation and move straight
to :ref:`Option 3`.

.. note::

If a user wishes to use the circuit cutting toolbox to
automatically find optimized wire cuts for a circuit too large for
the free version of CPLEX, they should acquire a license and install
the `full
version <https://www.ibm.com/products/ilog-cplex-optimization-studio>`__.
Users who wish to run within a containerized environment may skip the
pre-installation and move straight to :ref:`Option 3`.

Pre-Installation
^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -61,14 +51,6 @@ Upgrade pip and install the CKT package.
pip install --upgrade pip
pip install circuit-knitting-toolbox
Users intending to use the automatic cut finding functionality in the CutQC package should install the ``cplex`` optional dependency.

Adjust the options below to suit your needs.

.. code:: sh
pip install 'circuit-knitting-toolbox[cplex]'
.. _Option 2:

Expand All @@ -94,13 +76,11 @@ The next step is to install CKT to the virtual environment. If you plan on runni
notebook dependencies in order to run all the visualizations in the notebooks.
If you plan on developing in the repository, you may want to install the ``dev`` dependencies.

Users intending to use the automatic cut finding functionality in the CutQC package should install the ``cplex`` optional dependency.

Adjust the options below to suit your needs.

.. code:: sh
pip install tox notebook -e '.[notebook-dependencies,dev,cplex]'
pip install tox notebook -e '.[notebook-dependencies,dev]'
If you installed the notebook dependencies, you can get started with CKT by running the notebooks in the docs.

Expand Down Expand Up @@ -166,27 +146,6 @@ the only one that will be saved across different container runs.
Platform Support
^^^^^^^^^^^^^^^^

Users of Mac M1 or M2 chips and Windows users may have issues running certain components of CKT.

If you are using Linux or macOS with an Intel chip (i.e., not the
new M1 or M2 chips), everything should work natively, so we
recommend either :ref:`Option 1` or :ref:`Option 2`.

All users on ARM chips, as well as all Windows users, may have to
take care when installing the toolbox, depending on which tools they
intend to use.

- The automatic wire cut search in the ``cutqc`` package depends
on CPLEX, which is only available on Intel chips and is not yet available
for Python 3.12.

In each case, one method that is guaranteed to work is to :ref:`use
the toolbox within Docker <Option 3>`. Other methods include:

- Users on Apple's M series of chips may wish to install an x86
version of Python. For instance, `conda
<https://docs.conda.io/en/latest/miniconda.html>`__ users can run
``CONDA_SUBDIR=osx-64 conda create -n x86_venv python=3`` to
create a virtual environment that uses Python compiled for the x86
instruction set. No matter the installation method, there is a
performance cost due to emulation.
We expect this package to work on `any platform supported by Qiskit <https://docs.quantum.ibm.com/start/install#operating-system-support>`__. If
you are experiencing issues running the software on your device, you
may consider :ref:`using the toolbox within Docker <Option 3>`.
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@
Circuit Knitting is the process of decomposing a larger quantum circuit into many smaller circuits, executing those circuits on a quantum processor(s), and then knitting their results into a reconstruction of the original circuit's outcome.

The toolbox currently contains the following tools:
- Circuit Cutting [[1-6]](#references)
- Circuit Cutting [[1-5]](#references)

For a more detailed discussion on circuit cutting, check out our [technical guide](https://qiskit-extensions.github.io/circuit-knitting-toolbox/circuit_cutting/explanation/index.html#overview-of-circuit-cutting).

----------------------------------------------------------------------------------------------------

### Documentation
Expand All @@ -45,10 +46,10 @@ All CKT documentation is available at https://qiskit-extensions.github.io/circui

### Installation

We encourage installing CKT via ``pip``, when possible. Users intending to use the automatic cut finding functionality in the ``CutQC`` package should install the ``cplex`` optional dependency.
We encourage installing CKT via ``pip``, when possible.

```bash
pip install 'circuit-knitting-toolbox[cplex]'
pip install 'circuit-knitting-toolbox'
```

For information on installing from source, running CKT in a container, and platform support, refer to the [installation instructions](https://qiskit-extensions.github.io/circuit-knitting-toolbox/install.html) in the CKT documentation.
Expand All @@ -71,9 +72,7 @@ This project is meant to evolve rapidly and, as such, does not follow [Qiskit's

[4] Lukas Brenner, Christophe Piveteau, David Sutter, [Optimal wire cutting with classical communication](https://arxiv.org/abs/2302.03366), arXiv:2302.03366 [quant-ph].

[5] Wei Tang, Teague Tomesh, Martin Suchara, Jeffrey Larson, Margaret Martonosi, [CutQC: Using small quantum computers for large quantum circuit evaluations](https://doi.org/10.1145/3445814.3446758), Proceedings of the 26th ACM International Conference on Architectural Support for Programming Languages and Operating Systems. pp. 473 (2021).

[6] K. Temme, S. Bravyi, and J. M. Gambetta, [Error mitigation for short-depth quantum circuits](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.119.180509), Physical Review Letters, 119(18), (2017).
[5] K. Temme, S. Bravyi, and J. M. Gambetta, [Error mitigation for short-depth quantum circuits](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.119.180509), Physical Review Letters, 119(18), (2017).

----------------------------------------------------------------------------------------------------

Expand Down
15 changes: 0 additions & 15 deletions circuit_knitting/cutting/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,6 @@
qpd.generate_qpd_weights
qpd.decompose_qpd_instructions
qpd.qpdbasis_from_instruction
CutQC
=====
.. autosummary::
:toctree: ../stubs/
:nosignatures:
cutqc.run_subcircuit_instances
cutqc.generate_summation_terms
cutqc.build
cutqc.verify
cutqc.cut_circuit_wires
cutqc.evaluate_subcircuits
cutqc.reconstruct_full_distribution
"""

from .cutting_decomposition import (
Expand Down
11 changes: 10 additions & 1 deletion circuit_knitting/cutting/automated_cut_finding.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ def find_cuts(
``data`` field.
- sampling_overhead: The sampling overhead incurred from cutting the specified
gates and wires.
- minimum_reached: A bool indicating whether or not the search conclusively found
the minimum of cost function. ``minimum_reached = False`` could also mean that the
cost returned was actually the lowest possible cost but that the search was
not allowed to run long enough to prove that this was the case.
Raises:
ValueError: The input circuit contains a gate acting on more than 2 qubits.
Expand All @@ -63,6 +67,8 @@ def find_cuts(
seed=optimization.seed,
max_gamma=optimization.max_gamma,
max_backjumps=optimization.max_backjumps,
gate_lo=optimization.gate_lo,
wire_lo=optimization.wire_lo,
)

# Hard-code the optimizer to an LO-only optimizer
Expand Down Expand Up @@ -106,7 +112,7 @@ def find_cuts(
)
counter += 1

if action.action.get_name() == "CutBothWires": # pragma: no cover
if action.action.get_name() == "CutBothWires":
# There should be two wires specified in the action in this case
assert len(action.args) == 2
qubit_id2 = action.args[1][0] - 1
Expand All @@ -126,6 +132,7 @@ def find_cuts(
elif inst.operation.name == "cut_wire":
metadata["cuts"].append(("Wire Cut", i))
metadata["sampling_overhead"] = opt_out.upper_bound_gamma() ** 2
metadata["minimum_reached"] = optimizer.minimum_reached()

return circ_out, metadata

Expand All @@ -137,6 +144,8 @@ class OptimizationParameters:
seed: int | None = OptimizationSettings().seed
max_gamma: float = OptimizationSettings().max_gamma
max_backjumps: None | int = OptimizationSettings().max_backjumps
gate_lo: bool = OptimizationSettings().gate_lo
wire_lo: bool = OptimizationSettings().wire_lo


@dataclass
Expand Down
11 changes: 8 additions & 3 deletions circuit_knitting/cutting/cut_finding/cut_optimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,16 @@ def cut_optimization_cost_func(


def cut_optimization_upper_bound_cost_func(
goal_state, func_args: CutOptimizationFuncArgs
goal_state: DisjointSubcircuitsState, func_args: CutOptimizationFuncArgs
) -> tuple[float, float]:
"""Return the value of :math:`gamma` computed assuming all LO cuts."""
# pylint: disable=unused-argument
return (goal_state.upper_bound_gamma(), np.inf)
if goal_state is not None:
return (goal_state.upper_bound_gamma(), np.inf)
else:
raise ValueError(
"None state encountered: no cut state satisfying the specified constraints and settings could be found."
)


def cut_optimization_min_cost_bound_func(
Expand Down Expand Up @@ -125,7 +130,7 @@ def cut_optimization_goal_state_func(
# Global variable that holds the search-space functions for generating
# the cut optimization search space.
cut_optimization_search_funcs = SearchFunctions(
cost_func=cut_optimization_cost_func,
cost_func=cut_optimization_upper_bound_cost_func, # valid choice when considering only LO cuts.
upperbound_cost_func=cut_optimization_upper_bound_cost_func,
next_state_func=cut_optimization_next_state_func,
goal_state_func=cut_optimization_goal_state_func,
Expand Down
2 changes: 1 addition & 1 deletion circuit_knitting/cutting/cut_finding/cutting_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ def next_state_primitive(
new_state.bell_pairs.append((r2, rnew_2))
new_state.gamma_UB *= 16

new_state.add_action(self, gate_spec, ((1, w1, rnew_1), (2, w2, rnew_2)))
new_state.add_action(self, gate_spec, (1, w1, rnew_1), (2, w2, rnew_2))

return [new_state]

Expand Down
30 changes: 16 additions & 14 deletions circuit_knitting/cutting/cut_finding/disjoint_subcircuits_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,23 @@ class Action(NamedTuple):

action: DisjointSearchAction
gate_spec: GateSpec
args: list
args: list | tuple


class GateCutLocation(NamedTuple):
"""Named tuple for specification of gate cut location."""
class CutLocation(NamedTuple):
"""Named tuple for specifying cut locations.
This is used to specify instances of both :class:`CutTwoQubitGate` and :class:`CutBothWires`.
Both of these instances are fully specified by a gate reference.
"""

instruction_id: int
gate_name: str
qubits: Sequence


class WireCutLocation(NamedTuple):
"""Named tuple for specification of wire cut location.
"""Named tuple for specification of (single) wire cut locations.
Wire cuts are identified through the gates whose input wires are cut.
"""
Expand All @@ -64,10 +68,10 @@ class CutIdentifier(NamedTuple):
"""Named tuple for specification of location of :class:`CutTwoQubitGate` or :class:`CutBothWires` instances."""

cut_action: DisjointSearchAction
gate_cut_location: GateCutLocation
cut_location: CutLocation


class OneWireCutIdentifier(NamedTuple):
class SingleWireCutIdentifier(NamedTuple):
"""Named tuple for specification of location of :class:`CutLeftWire` or :class:`CutRightWire` instances."""

cut_action: DisjointSearchAction
Expand Down Expand Up @@ -130,15 +134,13 @@ def __init__(self, num_qubits: int | None = None, max_wire_cuts: int | None = No
if not (
num_qubits is None or (isinstance(num_qubits, int) and num_qubits >= 0)
):
raise ValueError("num_qubits must be either be None or a positive integer.")
raise ValueError("num_qubits must either be None or a positive integer.")

if not (
max_wire_cuts is None
or (isinstance(max_wire_cuts, int) and max_wire_cuts >= 0)
):
raise ValueError(
"max_wire_cuts must be either be None or a positive integer."
)
raise ValueError("max_wire_cuts must either be None or a positive integer.")

if num_qubits is None or max_wire_cuts is None:
self.wiremap: NDArray[np.int_] | None = None
Expand Down Expand Up @@ -213,7 +215,7 @@ def cut_actions_sublist(self) -> list[NamedTuple]:
for i in range(len(cut_actions)):
if cut_actions[i].action.get_name() in ("CutLeftWire", "CutRightWire"):
self.cut_actions_list.append(
OneWireCutIdentifier(
SingleWireCutIdentifier(
cut_actions[i].action.get_name(),
WireCutLocation(
cut_actions[i].gate_spec.instruction_id,
Expand All @@ -231,7 +233,7 @@ def cut_actions_sublist(self) -> list[NamedTuple]:
self.cut_actions_list.append(
CutIdentifier(
cut_actions[i].action.get_name(),
GateCutLocation(
CutLocation(
cut_actions[i].gate_spec.instruction_id,
cut_actions[i].gate_spec.gate.name,
cut_actions[i].gate_spec.gate.qubits,
Expand Down Expand Up @@ -430,12 +432,12 @@ def add_action(
self,
action_obj: DisjointSearchAction,
gate_spec: GateSpec,
args: tuple | None = None,
*args: tuple,
) -> None:
"""Append the specified action to the list of search-space actions that have been performed."""
if action_obj.get_name() is not None:
self.actions = cast(list, self.actions)
self.actions.append(Action(action_obj, gate_spec, [args]))
self.actions.append(Action(action_obj, gate_spec, args))

def get_search_level(self) -> int:
"""Return the search level."""
Expand Down
Loading

0 comments on commit 41b5881

Please sign in to comment.