Repository: PennyLaneAI/pennylane
Pull request #4819 (2023-11-10 12:26:06)

[Transform doc] Separate qcut
**Context:**
We want to make sure that qcut has a good place in the documentation and in PennyLane.

**Description of the Change:**
- qcut has its own folder
- qcut appears in API doc
- remove `qcut.py` file
- rename `montecarlo.py` to `cutcircuit_mc.py`

**Benefits:**
Better visibility of qcut (both in the project and in the docs).

github-actions[bot]: Hello. You may have forgotten to update the changelog!
Please edit [`doc/releases/changelog-dev.md`](/PennyLaneAI/pennylane/blob/master/doc/releases/changelog-dev.md) with:
* A one-to-two sentence description of the change. You may include a small working example for new features.
* A link back to this PR.
* Your name (or GitHub username) in the contributors section.
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/4819?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Comparison is base [(`45b89b6`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/commit/45b89b67d28bbe3f8a3f5ab49b0a80a07a92f6a9?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) 99.65% compared to head [(`bc66a1f`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/4819?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) 99.65%.


<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #4819      +/-   ##
==========================================
- Coverage   99.65%   99.65%   -0.01%     
==========================================
  Files         381      380       -1     
  Lines       34326    34319       -7     
==========================================
- Hits        34206    34199       -7     
  Misses        120      120              
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/4819?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).


Patch:
diff --git a/doc/code/qml_qcut.rst b/doc/code/qml_qcut.rst
new file mode 100644
index 000000000..e1ce5eaa5
--- /dev/null
+++ b/doc/code/qml_qcut.rst
@@ -0,0 +1,8 @@
+qml.qcut
+========
+
+
+.. currentmodule:: pennylane.qcut
+
+
+.. automodule:: pennylane.qcut
diff --git a/doc/index.rst b/doc/index.rst
index 122aa00ad..a491e3663 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -196,6 +196,7 @@ PennyLane is **free** and **open source**, released under the Apache License, Ve
    code/qml_ops_op_math
    code/qml_pauli
    code/qml_pulse
+   code/qml_qcut
    code/qml_qinfo
    code/qml_resource
    code/qml_shadows
diff --git a/doc/introduction/inspecting_circuits.rst b/doc/introduction/inspecting_circuits.rst
index dc93bf2bd..507ebcd62 100644
--- a/doc/introduction/inspecting_circuits.rst
+++ b/doc/introduction/inspecting_circuits.rst
@@ -218,12 +218,12 @@ False
 
 
 Another way to construct the "causal" DAG of a circuit is to use the
-:func:`~pennylane.transforms.qcut.tape_to_graph` function used by the ``qcut`` module. This
+:func:`~pennylane.qcut.tape_to_graph` function used by the ``qcut`` module. This
 function takes a quantum tape and creates a ``MultiDiGraph`` instance from the ``networkx`` python package.
 
 Using the above example, we get:
 
->>> g2 = qml.transforms.qcut.tape_to_graph(tape)
+>>> g2 = qml.qcut.tape_to_graph(tape)
 >>> type(g2)
 <class 'networkx.classes.multidigraph.MultiDiGraph'>
 >>> for k, v in g2.adjacency():
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index abfe74935..ce0646a98 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -216,6 +216,9 @@
 
 <h3>Breaking changes 💔</h3>
 
+* The transforms submodule `qml.transforms.qcut` becomes its own module `qml.qcut`.
+  [(#4819)](https://github.com/PennyLaneAI/pennylane/pull/4819)
+
 * The decomposition of `GroverOperator` now has an additional global phase operation.
   [(#4666)](https://github.com/PennyLaneAI/pennylane/pull/4666)
 
@@ -263,6 +266,9 @@
 
 <h3>Documentation 📝</h3>
 
+* Documentation for QCut was move to its own API page `qml.qcut`.
+  [(#4819)](https://github.com/PennyLaneAI/pennylane/pull/4819)
+
 * Documentation page for `qml.measurements` now links top-level accessible functions (e.g. `qml.expval`) 
   to their top-level pages (rather than their module-level pages, eg. `qml.measurements.expval`).
   [(#4750)](https://github.com/PennyLaneAI/pennylane/pull/4750)
@@ -353,6 +359,7 @@ Josh Izaac,
 Emiliano Godinez Ramirez,
 Ankit Khandelwal,
 Christina Lee,
+Romain Moyard,
 Vincent Michaud-Rioux,
 Anurav Modak,
 Mudit Pandey,
diff --git a/pennylane/__init__.py b/pennylane/__init__.py
index e7b7d3986..48b58b1da 100644
--- a/pennylane/__init__.py
+++ b/pennylane/__init__.py
@@ -86,8 +86,6 @@ from pennylane.transforms import (
     batch_input,
     batch_transform,
     batch_partial,
-    cut_circuit,
-    cut_circuit_mc,
     compile,
     defer_measurements,
     metric_tensor,
@@ -119,6 +117,7 @@ from pennylane.optimize import *
 from pennylane.vqe import ExpvalCost
 from pennylane.debugging import snapshots
 from pennylane.shadows import ClassicalShadow
+from pennylane.qcut import cut_circuit, cut_circuit_mc
 import pennylane.pulse
 
 import pennylane.fourier
diff --git a/pennylane/qcut/__init__.py b/pennylane/qcut/__init__.py
new file mode 100644
index 000000000..ef6e872c9
--- /dev/null
+++ b/pennylane/qcut/__init__.py
@@ -0,0 +1,142 @@
+# Copyright 2018-2021 Xanadu Quantum Technologies Inc.
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+#     http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+This module contains quantum function transforms for cutting quantum circuits.
+
+.. currentmodule:: pennylane
+
+Overview
+--------
+
+This module defines transform functions for circuit cutting. This allows
+for 'cutting' (or splitting) of large circuits into smaller circuits, to allow
+them to be executed on devices that have a restricted number of qubits.
+
+Transforms for circuit cutting
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. autosummary::
+    :toctree: api
+
+    ~cut_circuit
+    ~cut_circuit_mc
+
+
+Utility functions
+~~~~~~~~~~~~~~~~~
+
+There are also low-level functions that can be used to build up the circuit cutting functionalities:
+
+.. autosummary::
+    :toctree: api
+
+    ~qcut.tape_to_graph
+    ~qcut.replace_wire_cut_nodes
+    ~qcut.fragment_graph
+    ~qcut.graph_to_tape
+    ~qcut.expand_fragment_tape
+    ~qcut.expand_fragment_tapes_mc
+    ~qcut.qcut_processing_fn
+    ~qcut.qcut_processing_fn_sample
+    ~qcut.qcut_processing_fn_mc
+    ~qcut.CutStrategy
+    ~qcut.kahypar_cut
+    ~qcut.place_wire_cuts
+    ~qcut.find_and_place_cuts
+
+Cutting Circuits
+----------------
+
+Circuit cutting can allow you to replace a circuit with ``N`` wires by a set
+of circuits with less than ``N`` wires (see also
+`Peng et. al <https://arxiv.org/abs/1904.00102>`_). This comes
+with a cost: the smaller circuits require a greater number of device
+executions to be evaluated.
+
+In PennyLane, circuit cutting for circuits that terminate in expectation values
+can be activated by positioning :class:`~.pennylane.WireCut` operators at the
+desired cut locations, and by decorating the QNode with
+the :func:`~.pennylane.cut_circuit` transform.
+
+Cut circuits remain fully differentiable, and the resulting circuits can be
+executed on parallel devices if available. Please see the
+:func:`~.pennylane.cut_circuit` documentation for more details.
+
+.. note::
+
+    Simulated quantum circuits that produce samples can be cut using
+    the :func:`~.pennylane.cut_circuit_mc`
+    transform, which is based on the Monte Carlo method.
+
+Automatic cutting
+-----------------
+
+PennyLane also has experimental support for automatic cutting of circuits ---
+that is, the ability to determine optimum cut location without explicitly
+placing :class:`~.pennylane.WireCut` operators. This can be enabled by using the
+``auto_cutter`` keyword argument of :func:`~.pennylane.cut_circuit`; refer to the
+function documentation for more details.
+"""
+
+from .utils import (
+    replace_wire_cut_node,
+    replace_wire_cut_nodes,
+    fragment_graph,
+    find_and_place_cuts,
+    place_wire_cuts,
+    _remove_existing_cuts,
+    _get_optim_cut,
+    _is_valid_cut,
+    MeasureNode,
+    PrepareNode,
+    _prep_one_state,
+    _prep_zero_state,
+    _prep_plus_state,
+    _prep_minus_state,
+    _prep_iplus_state,
+    _prep_iminus_state,
+)
+from .tapes import (
+    graph_to_tape,
+    tape_to_graph,
+    expand_fragment_tape,
+    _qcut_expand_fn,
+    _get_measurements,
+    _find_new_wire,
+    _add_operator_node,
+)
+from .cutcircuit import cut_circuit, _cut_circuit_expand
+from .cutcircuit_mc import (
+    cut_circuit_mc,
+    _cut_circuit_mc_expand,
+    expand_fragment_tapes_mc,
+    MC_MEASUREMENTS,
+    MC_STATES,
+    _identity,
+    _pauliX,
+    _pauliY,
+    _pauliZ,
+)
+from .processing import (
+    qcut_processing_fn,
+    qcut_processing_fn_sample,
+    qcut_processing_fn_mc,
+    contract_tensors,
+    _process_tensor,
+    _to_tensors,
+    _reshape_results,
+    _get_symbol,
+)
+from .kahypar import kahypar_cut, _graph_to_hmetis
+from .cutstrategy import CutStrategy
diff --git a/pennylane/transforms/qcut/_cut_kKaHyPar_sea20.ini b/pennylane/qcut/_cut_kKaHyPar_sea20.ini
similarity index 100%
rename from pennylane/transforms/qcut/_cut_kKaHyPar_sea20.ini
rename to pennylane/qcut/_cut_kKaHyPar_sea20.ini
diff --git a/pennylane/transforms/qcut/cutcircuit.py b/pennylane/qcut/cutcircuit.py
similarity index 93%
rename from pennylane/transforms/qcut/cutcircuit.py
rename to pennylane/qcut/cutcircuit.py
index 80a955927..eec006931 100644
--- a/pennylane/transforms/qcut/cutcircuit.py
+++ b/pennylane/qcut/cutcircuit.py
@@ -195,14 +195,14 @@ def cut_circuit(
         .. autosummary::
             :toctree:
 
-            ~transforms.qcut.tape_to_graph
-            ~transforms.qcut.find_and_place_cuts
-            ~transforms.qcut.replace_wire_cut_nodes
-            ~transforms.qcut.fragment_graph
-            ~transforms.qcut.graph_to_tape
-            ~transforms.qcut.expand_fragment_tape
-            ~transforms.qcut.qcut_processing_fn
-            ~transforms.qcut.CutStrategy
+            ~qcut.tape_to_graph
+            ~qcut.find_and_place_cuts
+            ~qcut.replace_wire_cut_nodes
+            ~qcut.fragment_graph
+            ~qcut.graph_to_tape
+            ~qcut.expand_fragment_tape
+            ~qcut.qcut_processing_fn
+            ~qcut.CutStrategy
 
         The following shows how these elementary steps are combined as part of the
         ``cut_circuit()`` transform.
@@ -233,7 +233,7 @@ def cut_circuit(
 
         To cut the circuit, we first convert it to its graph representation:
 
-        >>> graph = qml.transforms.qcut.tape_to_graph(tape)
+        >>> graph = qml.qcut.tape_to_graph(tape)
 
         .. figure:: ../../_static/qcut_graph.svg
             :align: center
@@ -261,11 +261,11 @@ def cut_circuit(
             measurements = [qml.expval(qml.pauli.string_to_pauli_word("ZZZ"))]
             uncut_tape = qml.tape.QuantumTape(ops, measurements)
 
-        >>> cut_graph = qml.transforms.qcut.find_and_place_cuts(
-        ...     graph = qml.transforms.qcut.tape_to_graph(uncut_tape),
-        ...     cut_strategy = qml.transforms.qcut.CutStrategy(max_free_wires=2),
+        >>> cut_graph = qml.qcut.find_and_place_cuts(
+        ...     graph = qml.qcut.tape_to_graph(uncut_tape),
+        ...     cut_strategy = qml.qcut.CutStrategy(max_free_wires=2),
         ... )
-        >>> print(qml.transforms.qcut.graph_to_tape(cut_graph).draw())
+        >>> print(qml.qcut.graph_to_tape(cut_graph).draw())
         0: ──RX─╭●──RY────┤ ╭<Z@Z@Z>
         1: ──RY─╰Z──//─╭●─┤ ├<Z@Z@Z>
         2: ──RX────────╰Z─┤ ╰<Z@Z@Z>
@@ -273,7 +273,7 @@ def cut_circuit(
         Our next step is to remove the :class:`~.WireCut` nodes in the graph and replace with
         :class:`~.MeasureNode` and :class:`~.PrepareNode` pairs.
 
-        >>> qml.transforms.qcut.replace_wire_cut_nodes(graph)
+        >>> qml.qcut.replace_wire_cut_nodes(graph)
 
         The :class:`~.MeasureNode` and :class:`~.PrepareNode` pairs are placeholder operations that
         allow us to cut the circuit graph and then iterate over measurement and preparation
@@ -282,11 +282,11 @@ def cut_circuit(
         `communication_graph <https://en.wikipedia.org/wiki/Quotient_graph>`__
         detailing the connectivity between the components.
 
-        >>> fragments, communication_graph = qml.transforms.qcut.fragment_graph(graph)
+        >>> fragments, communication_graph = qml.qcut.fragment_graph(graph)
 
         We now convert the ``fragments`` back to :class:`~.QuantumTape` objects
 
-        >>> fragment_tapes = [qml.transforms.qcut.graph_to_tape(f) for f in fragments]
+        >>> fragment_tapes = [qml.qcut.graph_to_tape(f) for f in fragments]
 
         The circuit fragments can now be visualized:
 
@@ -308,7 +308,7 @@ def cut_circuit(
 
         .. code-block::
 
-            expanded = [qml.transforms.qcut.expand_fragment_tape(t) for t in fragment_tapes]
+            expanded = [qml.qcut.expand_fragment_tape(t) for t in fragment_tapes]
 
             configurations = []
             prepare_nodes = []
@@ -353,7 +353,7 @@ def cut_circuit(
         output via a tensor network contraction
 
         >>> results = qml.execute(tapes, dev, gradient_fn=None)
-        >>> qml.transforms.qcut.qcut_processing_fn(
+        >>> qml.qcut.qcut_processing_fn(
         ...     results,
         ...     communication_graph,
         ...     prepare_nodes,
diff --git a/pennylane/transforms/qcut/montecarlo.py b/pennylane/qcut/cutcircuit_mc.py
similarity index 93%
rename from pennylane/transforms/qcut/montecarlo.py
rename to pennylane/qcut/cutcircuit_mc.py
index b860a8302..864e59a97 100644
--- a/pennylane/transforms/qcut/montecarlo.py
+++ b/pennylane/qcut/cutcircuit_mc.py
@@ -32,7 +32,12 @@ from pennylane.wires import Wires
 from .cutstrategy import CutStrategy
 from .kahypar import kahypar_cut
 from .processing import qcut_processing_fn_mc, qcut_processing_fn_sample
-from .qcut import (
+
+from .tapes import _qcut_expand_fn, graph_to_tape, tape_to_graph
+from .utils import (
+    find_and_place_cuts,
+    fragment_graph,
+    replace_wire_cut_nodes,
     MeasureNode,
     PrepareNode,
     _prep_iminus_state,
@@ -42,8 +47,6 @@ from .qcut import (
     _prep_plus_state,
     _prep_zero_state,
 )
-from .tapes import _qcut_expand_fn, graph_to_tape, tape_to_graph
-from .utils import find_and_place_cuts, fragment_graph, replace_wire_cut_nodes
 
 
 def _cut_circuit_mc_expand(
@@ -202,14 +205,14 @@ def cut_circuit_mc(
         .. autosummary::
             :toctree:
 
-            ~transforms.qcut.tape_to_graph
-            ~transforms.qcut.find_and_place_cuts
-            ~transforms.qcut.replace_wire_cut_nodes
-            ~transforms.qcut.fragment_graph
-            ~transforms.qcut.graph_to_tape
-            ~transforms.qcut.expand_fragment_tapes_mc
-            ~transforms.qcut.qcut_processing_fn_sample
-            ~transforms.qcut.qcut_processing_fn_mc
+            ~qcut.tape_to_graph
+            ~qcut.find_and_place_cuts
+            ~qcut.replace_wire_cut_nodes
+            ~qcut.fragment_graph
+            ~qcut.graph_to_tape
+            ~qcut.expand_fragment_tapes_mc
+            ~qcut.qcut_processing_fn_sample
+            ~qcut.qcut_processing_fn_mc
 
         The following shows how these elementary steps are combined as part of the
         ``cut_circuit_mc()`` transform.
@@ -237,7 +240,7 @@ def cut_circuit_mc(
 
         To cut the circuit, we first convert it to its graph representation:
 
-        >>> graph = qml.transforms.qcut.tape_to_graph(tape)
+        >>> graph = qml.qcut.tape_to_graph(tape)
 
         If, however, the optimal location of the :class:`~.WireCut` is unknown, we can use
         :func:`~.find_and_place_cuts` to make attempts in automatically finding such a cut
@@ -256,11 +259,11 @@ def cut_circuit_mc(
             measurements = [qml.sample(wires=[0, 1, 2])]
             uncut_tape = qml.tape.QuantumTape(ops, measurements)
 
-        >>> cut_graph = qml.transforms.qcut.find_and_place_cuts(
-        ...     graph=qml.transforms.qcut.tape_to_graph(uncut_tape),
-        ...     cut_strategy=qml.transforms.qcut.CutStrategy(max_free_wires=2),
+        >>> cut_graph = qml.qcut.find_and_place_cuts(
+        ...     graph=qml.qcut.tape_to_graph(uncut_tape),
+        ...     cut_strategy=qml.qcut.CutStrategy(max_free_wires=2),
         ... )
-        >>> print(qml.transforms.qcut.graph_to_tape(cut_graph).draw())
+        >>> print(qml.qcut.graph_to_tape(cut_graph).draw())
          0: ──H─╭●───────────┤  Sample[|1⟩⟨1|]
          1: ────╰X──//──X─╭●─┤  Sample[|1⟩⟨1|]
          2: ──────────────╰X─┤  Sample[|1⟩⟨1|]
@@ -268,7 +271,7 @@ def cut_circuit_mc(
         Our next step, using the original manual cut placement, is to remove the :class:`~.WireCut`
         nodes in the graph and replace with :class:`~.MeasureNode` and :class:`~.PrepareNode` pairs.
 
-        >>> qml.transforms.qcut.replace_wire_cut_nodes(graph)
+        >>> qml.qcut.replace_wire_cut_nodes(graph)
 
         The :class:`~.MeasureNode` and :class:`~.PrepareNode` pairs are placeholder operations that
         allow us to cut the circuit graph and then randomly select measurement and preparation
@@ -277,11 +280,11 @@ def cut_circuit_mc(
         `communication_graph <https://en.wikipedia.org/wiki/Quotient_graph>`__
         detailing the connectivity between the components.
 
-        >>> fragments, communication_graph = qml.transforms.qcut.fragment_graph(graph)
+        >>> fragments, communication_graph = qml.qcut.fragment_graph(graph)
 
         We now convert the ``fragments`` back to :class:`~.QuantumTape` objects
 
-        >>> fragment_tapes = [qml.transforms.qcut.graph_to_tape(f) for f in fragments]
+        >>> fragment_tapes = [qml.qcut.graph_to_tape(f) for f in fragments]
 
         The circuit fragments can now be visualized:
 
@@ -315,7 +318,7 @@ def cut_circuit_mc(
         is determined by the number of shots.
 
         >>> shots = 3
-        >>> configurations, settings = qml.transforms.qcut.expand_fragment_tapes_mc(
+        >>> configurations, settings = qml.qcut.expand_fragment_tapes_mc(
         ...     fragment_tapes, communication_graph, shots=shots
         ... )
         >>> tapes = tuple(tape for c in configurations for tape in c)
@@ -353,7 +356,7 @@ def cut_circuit_mc(
         output bitstrings.
 
         >>> results = qml.execute(tapes, dev, gradient_fn=None)
-        >>> qml.transforms.qcut.qcut_processing_fn_sample(
+        >>> qml.qcut.qcut_processing_fn_sample(
         ...     results,
         ...     communication_graph,
         ...     shots=shots,
@@ -374,7 +377,7 @@ def cut_circuit_mc(
                 if x[0] == 1:
                     return -1
 
-        >>> qml.transforms.qcut.qcut_processing_fn_mc(
+        >>> qml.qcut.qcut_processing_fn_mc(
         ...     results,
         ...     communication_graph,
         ...     settings,
@@ -636,17 +639,17 @@ def expand_fragment_tapes_mc(
 
     We can generate the fragment tapes using the following workflow:
 
-    >>> g = qml.transforms.qcut.tape_to_graph(tape)
-    >>> qml.transforms.qcut.replace_wire_cut_nodes(g)
-    >>> subgraphs, communication_graph = qml.transforms.qcut.fragment_graph(g)
-    >>> tapes = [qml.transforms.qcut.graph_to_tape(sg) for sg in subgraphs]
+    >>> g = qml.qcut.tape_to_graph(tape)
+    >>> qml.qcut.replace_wire_cut_nodes(g)
+    >>> subgraphs, communication_graph = qml.qcut.fragment_graph(g)
+    >>> tapes = [qml.qcut.graph_to_tape(sg) for sg in subgraphs]
 
     We can then expand over the measurement and preparation nodes to generate random
     configurations using:
 
     .. code-block:: python
 
-        >>> configs, settings = qml.transforms.qcut.expand_fragment_tapes_mc(tapes, communication_graph, 3)
+        >>> configs, settings = qml.qcut.expand_fragment_tapes_mc(tapes, communication_graph, 3)
         >>> print(settings)
         [[1 6 2]]
         >>> for i, (c1, c2) in enumerate(zip(configs[0], configs[1])):
diff --git a/pennylane/transforms/qcut/cutstrategy.py b/pennylane/qcut/cutstrategy.py
similarity index 100%
rename from pennylane/transforms/qcut/cutstrategy.py
rename to pennylane/qcut/cutstrategy.py
diff --git a/pennylane/transforms/qcut/kahypar.py b/pennylane/qcut/kahypar.py
similarity index 98%
rename from pennylane/transforms/qcut/kahypar.py
rename to pennylane/qcut/kahypar.py
index 10f9cd9a7..94c006fda 100644
--- a/pennylane/transforms/qcut/kahypar.py
+++ b/pennylane/qcut/kahypar.py
@@ -90,8 +90,8 @@ def kahypar_cut(
 
     We can let KaHyPar automatically find the optimal edges to place cuts:
 
-    >>> graph = qml.transforms.qcut.tape_to_graph(tape)
-    >>> cut_edges = qml.transforms.qcut.kahypar_cut(
+    >>> graph = qml.qcut.tape_to_graph(tape)
+    >>> cut_edges = qml.qcut.kahypar_cut(
             graph=graph,
             num_fragments=2,
         )
diff --git a/pennylane/transforms/qcut/processing.py b/pennylane/qcut/processing.py
similarity index 99%
rename from pennylane/transforms/qcut/processing.py
rename to pennylane/qcut/processing.py
index 9c31ec968..d768b14c3 100644
--- a/pennylane/transforms/qcut/processing.py
+++ b/pennylane/qcut/processing.py
@@ -22,7 +22,7 @@ from networkx import MultiDiGraph
 import pennylane as qml
 from pennylane import numpy as np
 
-from .qcut import MeasureNode, PrepareNode
+from .utils import MeasureNode, PrepareNode
 
 
 def qcut_processing_fn(
@@ -298,7 +298,7 @@ def contract_tensors(
 
     The network can then be contracted using:
 
-    >>> qml.transforms.qcut.contract_tensors(tensors, graph, prep, meas)
+    >>> qml.qcut.contract_tensors(tensors, graph, prep, meas)
     38
     """
     # pylint: disable=import-outside-toplevel
diff --git a/pennylane/transforms/qcut/tapes.py b/pennylane/qcut/tapes.py
similarity index 96%
rename from pennylane/transforms/qcut/tapes.py
rename to pennylane/qcut/tapes.py
index a29836dcf..b7c0a3588 100644
--- a/pennylane/transforms/qcut/tapes.py
+++ b/pennylane/qcut/tapes.py
@@ -31,7 +31,7 @@ from pennylane.queuing import AnnotatedQueue, WrappedObj
 from pennylane.tape import QuantumScript, QuantumTape
 from pennylane.wires import Wires
 
-from .qcut import (
+from .utils import (
     MeasureNode,
     PrepareNode,
     _prep_iplus_state,
@@ -74,7 +74,7 @@ def tape_to_graph(tape: QuantumTape) -> MultiDiGraph:
 
     Its corresponding circuit graph can be found using
 
-    >>> qml.transforms.qcut.tape_to_graph(tape)
+    >>> qml.qcut.tape_to_graph(tape)
     <networkx.classes.multidigraph.MultiDiGraph at 0x7fe41cbd7210>
     """
     graph = MultiDiGraph()
@@ -138,8 +138,8 @@ def graph_to_tape(graph: MultiDiGraph) -> QuantumTape:
             qml.RX(0.4, wires=0),
             qml.RY(0.5, wires=1),
             qml.CNOT(wires=[0, 1]),
-            qml.transforms.qcut.MeasureNode(wires=1),
-            qml.transforms.qcut.PrepareNode(wires=1),
+            qml.qcut.MeasureNode(wires=1),
+            qml.qcut.PrepareNode(wires=1),
             qml.CNOT(wires=[1, 0]),
         ]
         measurements = [qml.expval(qml.PauliZ(0))]
@@ -148,8 +148,8 @@ def graph_to_tape(graph: MultiDiGraph) -> QuantumTape:
     This circuit contains operations that follow a :class:`~.MeasureNode`. These operations will
     subsequently act on wire ``2`` instead of wire ``1``:
 
-    >>> graph = qml.transforms.qcut.tape_to_graph(tape)
-    >>> tape = qml.transforms.qcut.graph_to_tape(graph)
+    >>> graph = qml.qcut.tape_to_graph(tape)
+    >>> tape = qml.qcut.graph_to_tape(graph)
     >>> print(tape.draw())
     0: ──RX──────────╭●──────────────╭X─┤  <Z>
     1: ──RY──────────╰X──MeasureNode─│──┤
@@ -268,15 +268,15 @@ def expand_fragment_tape(
     .. code-block:: python
 
         ops = [
-            qml.transforms.qcut.PrepareNode(wires=0),
+            qml.qcut.PrepareNode(wires=0),
             qml.RX(0.5, wires=0),
-            qml.transforms.qcut.MeasureNode(wires=0),
+            qml.qcut.MeasureNode(wires=0),
         ]
         tape = qml.tape.QuantumTape(ops)
 
     We can expand over the measurement and preparation nodes using:
 
-    >>> tapes, prep, meas = qml.transforms.qcut.expand_fragment_tape(tape)
+    >>> tapes, prep, meas = qml.qcut.expand_fragment_tape(tape)
     >>> for t in tapes:
     ...     print(qml.drawer.tape_text(t, decimals=1))
     0: ──I──RX(0.5)─┤  <I>  <Z>
diff --git a/pennylane/transforms/qcut/utils.py b/pennylane/qcut/utils.py
similarity index 91%
rename from pennylane/transforms/qcut/utils.py
rename to pennylane/qcut/utils.py
index ffd2a98aa..bdf74269c 100644
--- a/pennylane/transforms/qcut/utils.py
+++ b/pennylane/qcut/utils.py
@@ -17,19 +17,71 @@ Support functions for cut_circuit and cut_circuit_mc.
 
 
 import warnings
+import uuid
 from typing import Any, Callable, Sequence, Tuple
 from networkx import MultiDiGraph, has_path, weakly_connected_components
 
+import pennylane as qml
 from pennylane import numpy as np
 from pennylane.measurements import MeasurementProcess
-from pennylane.operation import Operation
 from pennylane.ops.meta import WireCut
 from pennylane.queuing import WrappedObj
+from pennylane.operation import Operation
 
 from .kahypar import kahypar_cut
 from .cutstrategy import CutStrategy
-from .tapes import graph_to_tape
-from .qcut import MeasureNode, PrepareNode
+
+
+class MeasureNode(Operation):
+    """Placeholder node for measurement operations"""
+
+    num_wires = 1
+    grad_method = None
+
+    def __init__(self, *params, wires=None, id=None):
+        id = id or str(uuid.uuid4())
+
+        super().__init__(*params, wires=wires, id=id)
+
+
+class PrepareNode(Operation):
+    """Placeholder node for state preparations"""
+
+    num_wires = 1
+    grad_method = None
+
+    def __init__(self, *params, wires=None, id=None):
+        id = id or str(uuid.uuid4())
+
+        super().__init__(*params, wires=wires, id=id)
+
+
+def _prep_zero_state(wire):
+    qml.Identity(wire)
+
+
+def _prep_one_state(wire):
+    qml.PauliX(wire)
+
+
+def _prep_plus_state(wire):
+    qml.Hadamard(wire)
+
+
+def _prep_minus_state(wire):
+    qml.PauliX(wire)
+    qml.Hadamard(wire)
+
+
+def _prep_iplus_state(wire):
+    qml.Hadamard(wire)
+    qml.S(wires=wire)
+
+
+def _prep_iminus_state(wire):
+    qml.PauliX(wire)
+    qml.Hadamard(wire)
+    qml.S(wires=wire)
 
 
 def find_and_place_cuts(
@@ -99,8 +151,8 @@ def find_and_place_cuts(
     Since the existing :class:`~.WireCut` doesn't sufficiently fragment the circuit, we can find the
     remaining cuts using the default KaHyPar partitioner:
 
-    >>> graph = qml.transforms.qcut.tape_to_graph(tape)
-    >>> cut_graph = qml.transforms.qcut.find_and_place_cuts(
+    >>> graph = qml.qcut.tape_to_graph(tape)
+    >>> cut_graph = qml.qcut.find_and_place_cuts(
             graph=graph,
             num_fragments=2,
             imbalance=0.5,
@@ -108,7 +160,7 @@ def find_and_place_cuts(
 
     Visualizing the newly-placed cut:
 
-    >>> print(qml.transforms.qcut.graph_to_tape(cut_graph).draw())
+    >>> print(qml.qcut.graph_to_tape(cut_graph).draw())
      0: ──RX(0.1)──╭●───────────────╭●────────╭┤ ⟨X ⊗ Y ⊗ Z⟩
      1: ──RY(0.2)──╰X──//──╭●───//──╰X────────│┤
      a: ──RX(0.3)──╭●──────╰X──╭●────RX(0.5)──├┤ ⟨X ⊗ Y ⊗ Z⟩
@@ -119,15 +171,15 @@ def find_and_place_cuts(
     into fragments. Or, alternatively, we can directly get such processed graph by passing
     ``replace_wire_cuts=True``:
 
-    >>> cut_graph = qml.transforms.qcut.find_and_place_cuts(
+    >>> cut_graph = qml.qcut.find_and_place_cuts(
             graph=graph,
             num_fragments=2,
             imbalance=0.5,
             replace_wire_cuts=True,
         )
-    >>> frags, comm_graph = qml.transforms.qcut.fragment_graph(cut_graph)
+    >>> frags, comm_graph = qml.qcut.fragment_graph(cut_graph)
     >>> for t in frags:
-    ...     print(qml.transforms.qcut.graph_to_tape(t).draw())
+    ...     print(qml.qcut.graph_to_tape(t).draw())
 
     .. code-block::
 
@@ -145,7 +197,7 @@ def find_and_place_cuts(
     simple cut strategy is to simply specify the the ``max_free_wires`` argument (or equivalently
     directly passing a :class:`pennylane.Device` to the ``device`` argument):
 
-    >>> cut_strategy = qml.transforms.qcut.CutStrategy(max_free_wires=2)
+    >>> cut_strategy = qml.qcut.CutStrategy(max_free_wires=2)
     >>> print(cut_strategy.get_cut_kwargs(graph))
      [{'num_fragments': 2, 'imbalance': 0.5714285714285714},
       {'num_fragments': 3, 'imbalance': 1.4},
@@ -165,11 +217,11 @@ def find_and_place_cuts(
     in order to search for the optimal cut. This is done by directly passing a
     :class:`~.CutStrategy` to :func:`~.find_and_place_cuts`:
 
-    >>> cut_graph = qml.transforms.qcut.find_and_place_cuts(
+    >>> cut_graph = qml.qcut.find_and_place_cuts(
             graph=graph,
             cut_strategy=cut_strategy,
         )
-    >>> print(qml.transforms.qcut.graph_to_tape(cut_graph).draw())
+    >>> print(qml.qcut.graph_to_tape(cut_graph).draw())
      0: ──RX──//─╭●──//────────╭●──//─────────┤ ╭<X@Y@Z>
      1: ──RY──//─╰X──//─╭●──//─╰X─────────────┤ │
      a: ──RX──//─╭●──//─╰X──//─╭●──//──RX──//─┤ ├<X@Y@Z>
@@ -178,10 +230,10 @@ def find_and_place_cuts(
     As one can tell, quite a few cuts have to be made in order to execute the circuit on solely
     2-qubit devices. To verify, let's print the fragments:
 
-    >>> qml.transforms.qcut.replace_wire_cut_nodes(cut_graph)
-    >>> frags, comm_graph = qml.transforms.qcut.fragment_graph(cut_graph)
+    >>> qml.qcut.replace_wire_cut_nodes(cut_graph)
+    >>> frags, comm_graph = qml.qcut.fragment_graph(cut_graph)
     >>> for t in frags:
-    ...     print(qml.transforms.qcut.graph_to_tape(t).draw())
+    ...     print(qml.qcut.graph_to_tape(t).draw())
 
     .. code-block::
 
@@ -315,8 +367,8 @@ def replace_wire_cut_node(node: WireCut, graph: MultiDiGraph):
 
     We can find the circuit graph and remove the wire cut node using:
 
-    >>> graph = qml.transforms.qcut.tape_to_graph(tape)
-    >>> qml.transforms.qcut.replace_wire_cut_node(wire_cut, graph)
+    >>> graph = qml.qcut.tape_to_graph(tape)
+    >>> qml.qcut.replace_wire_cut_node(wire_cut, graph)
     """
     node_obj = WrappedObj(node)
     predecessors = graph.pred[node_obj]
@@ -398,8 +450,8 @@ def replace_wire_cut_nodes(graph: MultiDiGraph):
 
     We can find the circuit graph and remove all the wire cut nodes using:
 
-    >>> graph = qml.transforms.qcut.tape_to_graph(tape)
-    >>> qml.transforms.qcut.replace_wire_cut_nodes(graph)
+    >>> graph = qml.qcut.tape_to_graph(tape)
+    >>> qml.qcut.replace_wire_cut_nodes(graph)
     """
     for op in list(graph.nodes):
         if isinstance(op.obj, WireCut):
@@ -442,7 +494,7 @@ def place_wire_cuts(
     ``RY(0.543, wires=["a"])`` and ``CNOT(wires=[0, 'a'])`` operations after the tape is constructed,
     we can first find the edge in the graph:
 
-    >>> graph = qml.transforms.qcut.tape_to_graph(tape)
+    >>> graph = qml.qcut.tape_to_graph(tape)
     >>> op0, op1 = tape.operations[1], tape.operations[2]
     >>> cut_edges = [e for e in graph.edges if e[0] is op0 and e[1] is op1]
     >>> cut_edges
@@ -450,13 +502,13 @@ def place_wire_cuts(
 
     Then feed it to this function for placement:
 
-    >>> cut_graph = qml.transforms.qcut.place_wire_cuts(graph=graph, cut_edges=cut_edges)
+    >>> cut_graph = qml.qcut.place_wire_cuts(graph=graph, cut_edges=cut_edges)
     >>> cut_graph
     <networkx.classes.multidigraph.MultiDiGraph at 0x7f7251ac1220>
 
     And visualize the cut by converting back to a tape:
 
-    >>> print(qml.transforms.qcut.graph_to_tape(cut_graph).draw())
+    >>> print(qml.qcut.graph_to_tape(cut_graph).draw())
      0: ──RX(0.432)──────╭●──┤ ⟨Z⟩
      a: ──RY(0.543)──//──╰X──┤
     """
@@ -562,9 +614,9 @@ def fragment_graph(graph: MultiDiGraph) -> Tuple[Tuple[MultiDiGraph], MultiDiGra
     We can find the corresponding graph, remove all the wire cut nodes, and
     find the subgraphs and communication graph by using:
 
-    >>> graph = qml.transforms.qcut.tape_to_graph(tape)
-    >>> qml.transforms.qcut.replace_wire_cut_nodes(graph)
-    >>> qml.transforms.qcut.fragment_graph(graph)
+    >>> graph = qml.qcut.tape_to_graph(tape)
+    >>> qml.qcut.replace_wire_cut_nodes(graph)
+    >>> qml.qcut.fragment_graph(graph)
     ((<networkx.classes.multidigraph.MultiDiGraph object at 0x7fb3b2311940>,
       <networkx.classes.multidigraph.MultiDiGraph object at 0x7fb3b2311c10>,
       <networkx.classes.multidigraph.MultiDiGraph object at 0x7fb3b23e2820>,
@@ -651,7 +703,7 @@ def _is_valid_cut(
     best_candidate_yet = (key not in cut_candidates) or (len(cut_candidates[key]) > num_cuts)
     # pylint: disable=no-member
     all_fragments_fit = all(
-        len(graph_to_tape(f).wires) <= max_free_wires for j, f in enumerate(fragments)
+        len(qml.qcut.graph_to_tape(f).wires) <= max_free_wires for j, f in enumerate(fragments)
     )
 
     return correct_num_fragments and best_candidate_yet and all_fragments_fit
diff --git a/pennylane/transforms/__init__.py b/pennylane/transforms/__init__.py
index d6512ed4e..b3dce3869 100644
--- a/pennylane/transforms/__init__.py
+++ b/pennylane/transforms/__init__.py
@@ -84,48 +84,6 @@ The following functions assist in decomposing operations to the Clifford+T basis
 
     ~transforms.sk_decomposition
 
-Transform for circuit cutting
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The :func:`~.cut_circuit` transform accepts a QNode and returns a new function that cuts the original circuit,
-allowing larger circuits to be split into smaller circuits that are compatible with devices that
-have a restricted number of qubits.
-
-.. autosummary::
-    :toctree: api
-
-    ~cut_circuit
-
-The :func:`~.cut_circuit_mc` transform is designed to be used for cutting circuits which contain :func:`~.sample`
-measurements and is implemented using a Monte Carlo method. Similarly to the :func:`~.cut_circuit`
-transform, this transform accepts a QNode and returns a new function that cuts the original circuit.
-This transform can also accept an optional classical processing function to calculate an
-expectation value.
-
-.. autosummary::
-    :toctree: api
-
-    ~cut_circuit_mc
-
-There are also low-level functions that can be used to build up the circuit cutting functionalities:
-
-.. autosummary::
-    :toctree: api
-
-    ~transforms.qcut.tape_to_graph
-    ~transforms.qcut.replace_wire_cut_nodes
-    ~transforms.qcut.fragment_graph
-    ~transforms.qcut.graph_to_tape
-    ~transforms.qcut.expand_fragment_tape
-    ~transforms.qcut.expand_fragment_tapes_mc
-    ~transforms.qcut.qcut_processing_fn
-    ~transforms.qcut.qcut_processing_fn_sample
-    ~transforms.qcut.qcut_processing_fn_mc
-    ~transforms.qcut.CutStrategy
-    ~transforms.qcut.kahypar_cut
-    ~transforms.qcut.place_wire_cuts
-    ~transforms.qcut.find_and_place_cuts
-
 Transforms for error mitigation
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -281,7 +239,5 @@ from .tape_expand import (
     set_decomposition,
 )
 from .transpile import transpile
-from . import qcut
-from .qcut import cut_circuit, cut_circuit_mc
 from .zx import to_zx, from_zx
 from .broadcast_expand import broadcast_expand
diff --git a/pennylane/transforms/qcut/__init__.py b/pennylane/transforms/qcut/__init__.py
deleted file mode 100644
index 49729b9dd..000000000
--- a/pennylane/transforms/qcut/__init__.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# Copyright 2018-2021 Xanadu Quantum Technologies Inc.
-
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-
-#     http://www.apache.org/licenses/LICENSE-2.0
-
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""
-This subpackage contains quantum function transforms for cutting quantum circuits.
-"""
-
-from .utils import (
-    replace_wire_cut_node,
-    replace_wire_cut_nodes,
-    fragment_graph,
-    find_and_place_cuts,
-    place_wire_cuts,
-    _remove_existing_cuts,
-    _get_optim_cut,
-    _is_valid_cut,
-)
-from .tapes import (
-    graph_to_tape,
-    tape_to_graph,
-    expand_fragment_tape,
-    _qcut_expand_fn,
-    _get_measurements,
-    _find_new_wire,
-    _add_operator_node,
-)
-from .cutcircuit import cut_circuit, _cut_circuit_expand
-from .montecarlo import (
-    cut_circuit_mc,
-    _cut_circuit_mc_expand,
-    expand_fragment_tapes_mc,
-    MC_MEASUREMENTS,
-    MC_STATES,
-    _identity,
-    _pauliX,
-    _pauliY,
-    _pauliZ,
-)
-from .processing import (
-    qcut_processing_fn,
-    qcut_processing_fn_sample,
-    qcut_processing_fn_mc,
-    contract_tensors,
-    _process_tensor,
-    _to_tensors,
-    _reshape_results,
-    _get_symbol,
-)
-from .kahypar import kahypar_cut, _graph_to_hmetis
-from .cutstrategy import CutStrategy
-from .qcut import (
-    MeasureNode,
-    PrepareNode,
-    _prep_one_state,
-    _prep_zero_state,
-    _prep_plus_state,
-    _prep_minus_state,
-    _prep_iplus_state,
-    _prep_iminus_state,
-)
diff --git a/pennylane/transforms/qcut/qcut.py b/pennylane/transforms/qcut/qcut.py
deleted file mode 100644
index e32dc5872..000000000
--- a/pennylane/transforms/qcut/qcut.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# Copyright 2022 Xanadu Quantum Technologies Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""
-Miscellaneous support for circuit cutting.
-"""
-
-
-import uuid
-
-import pennylane as qml
-from pennylane.operation import Operation
-
-
-class MeasureNode(Operation):
-    """Placeholder node for measurement operations"""
-
-    num_wires = 1
-    grad_method = None
-
-    def __init__(self, *params, wires=None, id=None):
-        id = id or str(uuid.uuid4())
-
-        super().__init__(*params, wires=wires, id=id)
-
-
-class PrepareNode(Operation):
-    """Placeholder node for state preparations"""
-
-    num_wires = 1
-    grad_method = None
-
-    def __init__(self, *params, wires=None, id=None):
-        id = id or str(uuid.uuid4())
-
-        super().__init__(*params, wires=wires, id=id)
-
-
-def _prep_zero_state(wire):
-    qml.Identity(wire)
-
-
-def _prep_one_state(wire):
-    qml.PauliX(wire)
-
-
-def _prep_plus_state(wire):
-    qml.Hadamard(wire)
-
-
-def _prep_minus_state(wire):
-    qml.PauliX(wire)
-    qml.Hadamard(wire)
-
-
-def _prep_iplus_state(wire):
-    qml.Hadamard(wire)
-    qml.S(wires=wire)
-
-
-def _prep_iminus_state(wire):
-    qml.PauliX(wire)
-    qml.Hadamard(wire)
-    qml.S(wires=wire)


Test patch:
diff --git a/tests/transforms/test_qcut.py b/tests/transforms/test_qcut.py
index a323448ad..e0c2405bf 100644
--- a/tests/transforms/test_qcut.py
+++ b/tests/transforms/test_qcut.py
@@ -34,8 +34,8 @@ from scipy.stats import unitary_group
 
 import pennylane as qml
 from pennylane import numpy as np
+from pennylane import qcut
 from pennylane.queuing import WrappedObj
-from pennylane.transforms import qcut
 from pennylane.wires import Wires
 
 pytestmark = pytest.mark.qcut
@@ -3061,7 +3061,7 @@ class TestCutCircuitMCTransform:
             qml.CNOT(wires=[0, 1])
             return qml.sample(wires=[0, 1])
 
-        spy = mocker.spy(qcut.montecarlo, "qcut_processing_fn_mc")
+        spy = mocker.spy(qcut.cutcircuit_mc, "qcut_processing_fn_mc")
         x = np.array(0.531, requires_grad=True)
         res = circuit(x)
 
@@ -3104,7 +3104,7 @@ class TestCutCircuitMCTransform:
             qml.CNOT(wires=[0, 1])
             return qml.sample(wires=[0, 1])
 
-        spy = mocker.spy(qcut.montecarlo, "qcut_processing_fn_mc")
+        spy = mocker.spy(qcut.cutcircuit_mc, "qcut_processing_fn_mc")
 
         x = 0.4
         res = circuit(x)
@@ -3163,7 +3163,7 @@ class TestCutCircuitMCTransform:
 
             return qml.sample(wires=[1, 2, 3])
 
-        spy = mocker.spy(qcut.montecarlo, "qcut_processing_fn_mc")
+        spy = mocker.spy(qcut.cutcircuit_mc, "qcut_processing_fn_mc")
 
         params = np.array([0.4, 0.5, 0.6, 0.7, 0.8], requires_grad=True)
         res = circuit(params)
@@ -4245,12 +4245,8 @@ class TestCutCircuitTransform:
         dev_2 = qml.device("default.qubit", wires=["Alice", 3.14, "Bob"])
 
         uncut_circuit = qml.QNode(circuit, dev_uncut)
-        cut_circuit_1 = qml.transforms.cut_circuit(
-            qml.QNode(circuit, dev_1), use_opt_einsum=use_opt_einsum
-        )
-        cut_circuit_2 = qml.transforms.cut_circuit(
-            qml.QNode(circuit, dev_2), use_opt_einsum=use_opt_einsum
-        )
+        cut_circuit_1 = qml.cut_circuit(qml.QNode(circuit, dev_1), use_opt_einsum=use_opt_einsum)
+        cut_circuit_2 = qml.cut_circuit(qml.QNode(circuit, dev_2), use_opt_einsum=use_opt_einsum)
 
         res_expected = uncut_circuit()
         res_1 = cut_circuit_1()
@@ -4267,7 +4263,7 @@ class TestCutCircuitTransform:
 
         dev = qml.device("default.qubit", wires=3)
 
-        @partial(qml.transforms.cut_circuit, use_opt_einsum=use_opt_einsum)
+        @partial(qml.cut_circuit, use_opt_einsum=use_opt_einsum)
         @qml.qnode(dev)
         def circuit(x):
             qml.RX(x, wires=0)
@@ -4289,7 +4285,7 @@ class TestCutCircuitTransform:
 
         dev = qml.device("default.qubit", wires=2)
 
-        @partial(qml.transforms.cut_circuit, use_opt_einsum=use_opt_einsum)
+        @partial(qml.cut_circuit, use_opt_einsum=use_opt_einsum)
         @qml.qnode(dev)
         def circuit(x):
             qml.RX(x, wires=0)
@@ -4514,7 +4510,7 @@ class TestCutCircuitExpansion:
             return qml.apply(measurement)
 
         spy = mocker.spy(qcut.cutcircuit, "_qcut_expand_fn")
-        spy_mc = mocker.spy(qcut.montecarlo, "_qcut_expand_fn")
+        spy_mc = mocker.spy(qcut.cutcircuit_mc, "_qcut_expand_fn")
 
         kwargs = {"shots": 10} if measurement.return_type is qml.measurements.Sample else {}
         cut_transform(circuit, device_wires=[0])(**kwargs)
@@ -4535,7 +4531,7 @@ class TestCutCircuitExpansion:
         tape = qml.tape.QuantumScript.from_queue(q)
         spy = mocker.spy(qcut.tapes, "_qcut_expand_fn")
         spy_cc = mocker.spy(qcut.cutcircuit, "_qcut_expand_fn")
-        spy_mc = mocker.spy(qcut.montecarlo, "_qcut_expand_fn")
+        spy_mc = mocker.spy(qcut.cutcircuit_mc, "_qcut_expand_fn")
 
         kwargs = {"shots": 10} if measurement.return_type is qml.measurements.Sample else {}
         cut_transform(tape, device_wires=[0], **kwargs)
@@ -4617,7 +4613,7 @@ class TestCutCircuitExpansion:
         qnode_cut = qcut.cut_circuit_mc(qml.QNode(circuit, dev_cut))
 
         spy_tapes = mocker.spy(qcut.tapes, "_qcut_expand_fn")
-        spy_mc = mocker.spy(qcut.montecarlo, "_qcut_expand_fn")
+        spy_mc = mocker.spy(qcut.cutcircuit_mc, "_qcut_expand_fn")
 
         qnode_cut(template_weights)
 
@@ -4897,7 +4893,7 @@ class TestKaHyPar:
         ),
     ]
     config_path = str(
-        Path(__file__).parent.parent.parent / "pennylane/transforms/qcut/_cut_kKaHyPar_sea20.ini"
+        Path(__file__).parent.parent.parent / "pennylane/qcut/_cut_kKaHyPar_sea20.ini"
     )
 
     def test_seed_in_ci(self):
@@ -5282,7 +5278,7 @@ class TestAutoCutCircuit:
 
         dev = qml.device("default.qubit", wires=3)
 
-        @partial(qml.transforms.cut_circuit, auto_cutter=True)
+        @partial(qml.cut_circuit, auto_cutter=True)
         @qml.qnode(dev)
         def circuit(x):
             qml.RX(x, wires=0)
@@ -5302,7 +5298,7 @@ class TestAutoCutCircuit:
 
         dev = qml.device("default.qubit", wires=2)
 
-        @partial(qml.transforms.cut_circuit, auto_cutter=True)
+        @partial(qml.cut_circuit, auto_cutter=True)
         @qml.qnode(dev)
         def circuit(x):
             qml.RX(x, wires=0)
@@ -5385,7 +5381,7 @@ class TestAutoCutCircuit:
         template_weights = [[0.1, -0.3]] * n_blocks
 
         device_size = 2
-        cut_strategy = qml.transforms.qcut.CutStrategy(max_free_wires=device_size)
+        cut_strategy = qml.qcut.CutStrategy(max_free_wires=device_size)
 
         with qml.queuing.AnnotatedQueue() as q0:
             qml.MPS(range(n_wires), n_block_wires, block, n_params_block, template_weights)
@@ -5415,13 +5411,6 @@ class TestAutoCutCircuit:
         assert all(len(set(e[2] for e in f.edges.data("wire"))) <= device_size for f in frags)
 
 
-class TestRedirect:
-    """Tests that redirect in qcut.__init__ works to maintain import pathways while reorganizing files"""
-
-    def test_qcut_redirects_to_qcut_qcut(self):
-        assert qml.transforms.qcut._prep_one_state == qml.transforms.qcut.qcut._prep_one_state
-
-
 class TestCutCircuitWithHamiltonians:
     """Integration tests for `cut_circuit` transform with Hamiltonians."""
 
@@ -5562,7 +5551,7 @@ class TestCutCircuitWithHamiltonians:
         template_weights = [[0.1, -0.3]] * n_blocks
 
         device_size = 2
-        cut_strategy = qml.transforms.qcut.CutStrategy(max_free_wires=device_size)
+        cut_strategy = qml.qcut.CutStrategy(max_free_wires=device_size)
 
         hamiltonian = qml.Hamiltonian(
             [1.0, 1.0],