From 4b31e2ffc4181862f29ae21989988dd2810dcce1 Mon Sep 17 00:00:00 2001 From: PabloAndresCQ Date: Wed, 17 Apr 2024 10:51:26 +0100 Subject: [PATCH 1/4] Now NetworkX is used as the default option for partition, and KaHyPar is left for advanced users --- .../cutensornet/structured_state/general.py | 5 +++++ .../structured_state/simulation.py | 19 ++++++++++++++----- setup.py | 2 +- tests/test_structured_state.py | 1 - 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/pytket/extensions/cutensornet/structured_state/general.py b/pytket/extensions/cutensornet/structured_state/general.py index 0d07c10e..7194b088 100644 --- a/pytket/extensions/cutensornet/structured_state/general.py +++ b/pytket/extensions/cutensornet/structured_state/general.py @@ -82,6 +82,7 @@ def __init__( float_precision: Type[Any] = np.float64, value_of_zero: float = 1e-16, leaf_size: int = 8, + use_kahypar: bool = False, k: int = 4, optim_delta: float = 1e-5, loglevel: int = logging.WARNING, @@ -113,6 +114,9 @@ def __init__( ``np.float64`` precision (default) and ``1e-7`` for ``np.float32``. leaf_size: For ``TTN`` simulation only. Sets the maximum number of qubits in a leaf node when using ``TTN``. Default is 8. + use_kahypar: Use KaHyPar for graph partitioning (used in ``TTN``) if this + is True. Otherwise, use NetworkX (worse, but easy to setup). Defaults + to False. k: For ``MPSxMPO`` simulation only. Sets the maximum number of layers the MPO is allowed to have before being contracted. Increasing this might increase fidelity, but it will also increase resource requirements @@ -177,6 +181,7 @@ def __init__( raise ValueError("Maximum allowed leaf_size is 65.") self.leaf_size = leaf_size + self.use_kahypar = use_kahypar self.k = k self.optim_delta = 1e-5 self.loglevel = loglevel diff --git a/pytket/extensions/cutensornet/structured_state/simulation.py b/pytket/extensions/cutensornet/structured_state/simulation.py index 0df64f1d..14d0768a 100644 --- a/pytket/extensions/cutensornet/structured_state/simulation.py +++ b/pytket/extensions/cutensornet/structured_state/simulation.py @@ -100,7 +100,9 @@ def simulate( sorted_gates = _get_sorted_gates(circuit, algorithm) elif algorithm == SimulationAlgorithm.TTNxGate: - qubit_partition = _get_qubit_partition(circuit, config.leaf_size) + qubit_partition = _get_qubit_partition( + circuit, config.leaf_size, config.use_kahypar + ) state = TTNxGate( # type: ignore libhandle, qubit_partition, @@ -163,7 +165,7 @@ def prepare_circuit_mps(circuit: Circuit) -> tuple[Circuit, dict[Qubit, Qubit]]: def _get_qubit_partition( - circuit: Circuit, max_q_per_leaf: int + circuit: Circuit, max_q_per_leaf: int, use_kahypar: bool ) -> dict[int, list[Qubit]]: """Returns a qubit partition for a TTN. @@ -174,6 +176,8 @@ def _get_qubit_partition( Args: circuit: The circuit to be simulated. max_q_per_leaf: The maximum allowed number of qubits per node leaf + use_kahypar: Use KaHyPar for graph partitioning if this is True. + Otherwise, use NetworkX (worse, but easy to setup). Returns: A dictionary describing the partition in the format expected by TTN. @@ -214,9 +218,14 @@ def _get_qubit_partition( old_partition = partition.copy() for key, group in old_partition.items(): # Apply the balanced bisection on this group - (groupA, groupB) = _apply_kahypar_bisection( - connectivity_graph.subgraph(group), - ) + if use_kahypar: # Using KaHyPar + (groupA, groupB) = _apply_kahypar_bisection( + connectivity_graph.subgraph(group), + ) + else: # Using NetworkX + (groupA, groupB) = nx.community.kernighan_lin_bisection( + connectivity_graph.subgraph(group), + ) # Groups A and B are on the same subtree (key separated by +1) partition[2 * key] = groupA partition[2 * key + 1] = groupB diff --git a/setup.py b/setup.py index c7d90902..bb98e8b6 100644 --- a/setup.py +++ b/setup.py @@ -42,7 +42,7 @@ license="Apache 2", packages=find_namespace_packages(include=["pytket.*"]), include_package_data=True, - install_requires=["pytket ~= 1.26"], + install_requires=["pytket ~= 1.26", "networkx >= 2.8"], classifiers=[ "Environment :: Console", "Programming Language :: Python :: 3.10", diff --git a/tests/test_structured_state.py b/tests/test_structured_state.py index 5617ca44..73675a6b 100644 --- a/tests/test_structured_state.py +++ b/tests/test_structured_state.py @@ -63,7 +63,6 @@ def test_copy(algorithm: SimulationAlgorithm) -> None: simple_circ = Circuit(2).H(0).H(1).CX(0, 1) with CuTensorNetHandle() as libhandle: - # Default config cfg = Config() state = simulate(libhandle, simple_circ, algorithm, cfg) From 1b0d24e92cf96affa19192a497cab66ee9d10f42 Mon Sep 17 00:00:00 2001 From: Pablo Andres-Martinez Date: Wed, 17 Apr 2024 03:07:41 -0700 Subject: [PATCH 2/4] Updated tests --- tests/test_structured_state.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_structured_state.py b/tests/test_structured_state.py index 73675a6b..f38f45f0 100644 --- a/tests/test_structured_state.py +++ b/tests/test_structured_state.py @@ -530,7 +530,7 @@ def test_circ_approx_explicit_ttn(circuit: Circuit) -> None: # Check for TTNxGate cfg = Config(truncation_fidelity=0.99, leaf_size=3, float_precision=np.float32) ttn_gate = simulate(libhandle, circuit, SimulationAlgorithm.TTNxGate, cfg) - assert np.isclose(ttn_gate.get_fidelity(), 0.769, atol=1e-3) + assert np.isclose(ttn_gate.get_fidelity(), 0.751, atol=1e-3) assert ttn_gate.is_valid() assert np.isclose(ttn_gate.vdot(ttn_gate), 1.0, atol=cfg._atol) @@ -538,7 +538,7 @@ def test_circ_approx_explicit_ttn(circuit: Circuit) -> None: # Check for TTNxGate cfg = Config(chi=120, leaf_size=3, float_precision=np.float32) ttn_gate = simulate(libhandle, circuit, SimulationAlgorithm.TTNxGate, cfg) - assert np.isclose(ttn_gate.get_fidelity(), 0.857, atol=1e-3) + assert np.isclose(ttn_gate.get_fidelity(), 0.854, atol=1e-3) assert ttn_gate.is_valid() assert np.isclose(ttn_gate.vdot(ttn_gate), 1.0, atol=cfg._atol) From bcb7366cb301362a031e60f9d30b32360d7df736 Mon Sep 17 00:00:00 2001 From: PabloAndresCQ Date: Wed, 17 Apr 2024 11:08:59 +0100 Subject: [PATCH 3/4] Updated changelog --- docs/changelog.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 84f4984e..75adb543 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,11 @@ Changelog ~~~~~~~~~ +0.6.1 (April 2024) +------------------ + +* When using ``simulate`` with ``TTNxGate`` algorithm, the initial partition is obtained using NetworkX instead of KaHyPar by default. This makes setup easier and means that ``TTNxGate`` can now be used when installing from PyPI. KaHyPar can still be used if ``use_kahypar`` from ``Config`` is set to True. + 0.6.0 (April 2024) ------------------ From 645bf8fd503b58851cdc6b2f28dc7a4f99165938 Mon Sep 17 00:00:00 2001 From: Pablo Andres-Martinez <104848389+PabloAndresCQ@users.noreply.github.com> Date: Wed, 17 Apr 2024 14:21:06 +0100 Subject: [PATCH 4/4] Update setup.py Co-authored-by: cqc-melf <70640934+cqc-melf@users.noreply.github.com> --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index bb98e8b6..6c7d1ebd 100644 --- a/setup.py +++ b/setup.py @@ -42,7 +42,7 @@ license="Apache 2", packages=find_namespace_packages(include=["pytket.*"]), include_package_data=True, - install_requires=["pytket ~= 1.26", "networkx >= 2.8"], + install_requires=["pytket ~= 1.26", "networkx ~= 3.0"], classifiers=[ "Environment :: Console", "Programming Language :: Python :: 3.10",