Repository: PennyLaneAI/pennylane

Issue:
[BUG] Error in docs example
### Expected behavior

The Bell State example in the [Measurements](https://pennylane.readthedocs.io/en/stable/introduction/measurements.html#combined-measurements) section of the docs should work.

### Actual behavior

It returns an error saying that you need to specify the number of shots.

QuantumFunctionError: The number of shots has to be explicitly set on the device when using sample-based measurements.

### Additional information

_No response_

### Source code

```shell
import pennylane as qml
from pennylane import numpy as np

dev = qml.device("default.qubit", wires=2)

@qml.qnode(dev)
def circuit():
    qml.Hadamard(wires=0)
    qml.CNOT(wires=[0, 1])
    return qml.sample(qml.PauliZ(0)), qml.sample(qml.PauliZ(1))

circuit()
```


### Tracebacks

_No response_

### System information

```shell
Name: PennyLane
Version: 0.22.0
```


### Existing GitHub issues

- [X] I have searched existing GitHub issues to make sure the issue does not already exist.


Discussion:

Resolving patch:
diff --git a/pennylane/transforms/control.py b/pennylane/transforms/control.py
--- a/pennylane/transforms/control.py
+++ b/pennylane/transforms/control.py
@@ -188,7 +188,8 @@ def ctrl(fn, control, control_values=None):
     Args:
         fn (function): Any python function that applies pennylane operations.
         control (Wires): The control wire(s).
-        control_values (list[int]): The values the control wire(s) should take.
+        control_values (int or list[int]): The value(s) the control wire(s) should take.
+            Integers other than 0 or 1 will be treated as ``int(bool(x))``.
 
     Returns:
         function: A new function that applies the controlled equivalent of ``fn``. The returned
@@ -240,7 +241,7 @@ def my_circuit2():
 
     .. Note::
 
-        Some devices are able to take advantage of the inherient sparsity of a
+        Some devices are able to take advantage of the inherent sparsity of a
         controlled operation. In those cases, it may be more efficient to use
         this transform rather than adding controls by hand. For devices that don't
         have special control support, the operation is expanded to add control wires
@@ -255,8 +256,8 @@ def my_circuit2():
         .. code-block:: python3
 
             # These two ops are equivalent.
-            op1 = qml.ctrl(qml.ctrl(my_ops, 1), 2)
-            op2 = qml.ctrl(my_ops, [2, 1])
+            op1 = qml.ctrl(qml.ctrl(ops, 1), 2)
+            op2 = qml.ctrl(ops, [2, 1])
 
         **Control Value Assignment**
 
@@ -264,16 +265,16 @@ def my_circuit2():
 
         .. code-block:: python3
 
-            op = qml.ctrl(qml.ctrl(my_ops, 1), 2, control_values=0)
-            op()
+            op = qml.ctrl(ops, 2, control_values=0)
+            op(params=[0.1, 0.2])
 
         This is equivalent to the following.
 
         .. code-block:: python3
 
             qml.PauliX(wires=2)
-            op = qml.ctrl(qml.ctrl(my_ops, 1), 2)
-            op()
+            op = qml.ctrl(ops, 2)
+            op(params=[0.1, 0.2])
             qml.PauliX(wires=2)
 
     """
diff --git a/pennylane/transforms/qcut.py b/pennylane/transforms/qcut.py
--- a/pennylane/transforms/qcut.py
+++ b/pennylane/transforms/qcut.py
@@ -967,7 +967,7 @@ def cut_circuit_mc(
     Args:
         tape (QuantumTape): the tape of the full circuit to be cut
         classical_processing_fn (callable): A classical postprocessing function to be applied to
-            the reconstructed bitstrings. The expected input is a bitstring; a flat array of length ``wires``.
+            the reconstructed bitstrings. The expected input is a bitstring; a flat array of length ``wires``,
             and the output should be a single number within the interval :math:`[-1, 1]`.
             If not supplied, the transform will output samples.
         auto_cutter (Union[bool, Callable]): Toggle for enabling automatic cutting with the default
@@ -1093,6 +1093,8 @@ def circuit(x):
 
         .. code-block:: python
 
+            np.random.seed(42)
+
             with qml.tape.QuantumTape() as tape:
                 qml.Hadamard(wires=0)
                 qml.CNOT(wires=[0, 1])
@@ -1126,9 +1128,9 @@ def circuit(x):
                 qml.sample(wires=[0, 1, 2])
 
         >>> 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),
-            )
+        ...     graph=qml.transforms.qcut.tape_to_graph(uncut_tape),
+        ...     cut_strategy=qml.transforms.qcut.CutStrategy(max_free_wires=2),
+        ... )
         >>> print(qml.transforms.qcut.graph_to_tape(cut_graph).draw())
          0: ──H─╭C───────────┤  Sample[|1⟩⟨1|]
          1: ────╰X──//──X─╭C─┤  Sample[|1⟩⟨1|]
@@ -1187,11 +1189,11 @@ def circuit(x):
 
         >>> shots = 3
         >>> configurations, settings = qml.transforms.qcut.expand_fragment_tapes_mc(
-        ...        fragment_tapes, communication_graph, shots=shots
-        ...    )
+        ...     fragment_tapes, communication_graph, shots=shots
+        ... )
         >>> tapes = tuple(tape for c in configurations for tape in c)
         >>> settings
-        tensor([[0, 4, 7]], requires_grad=True)
+        tensor([[6, 3, 4]], requires_grad=True)
 
         Each configuration is drawn below:
 
@@ -1202,21 +1204,21 @@ def circuit(x):
         .. code-block::
 
             0: ──H─╭C────┤  Sample[|1⟩⟨1|]
-            1: ────╰X──X─┤  Sample[I]
+            1: ────╰X──X─┤  Sample[Z]
 
             0: ──H─╭C────┤  Sample[|1⟩⟨1|]
-            1: ────╰X──X─┤  Sample[Y]
+            1: ────╰X──X─┤  Sample[X]
 
             0: ──H─╭C────┤  Sample[|1⟩⟨1|]
-            1: ────╰X──X─┤  Sample[Z]
+            1: ────╰X──X─┤  Sample[Y]
 
             0: ──I─╭C─┤  Sample[|1⟩⟨1|]
             1: ────╰X─┤  Sample[|1⟩⟨1|]
 
-            0: ──H──S─╭C─┤  Sample[|1⟩⟨1|]
+            0: ──X──S─╭C─┤  Sample[|1⟩⟨1|]
             1: ───────╰X─┤  Sample[|1⟩⟨1|]
 
-            0: ──X─╭C─┤  Sample[|1⟩⟨1|]
+            0: ──H─╭C─┤  Sample[|1⟩⟨1|]
             1: ────╰X─┤  Sample[|1⟩⟨1|]
 
         The last step is to execute the tapes and postprocess the results using
@@ -1229,9 +1231,9 @@ def circuit(x):
         ...     communication_graph,
         ...     shots=shots,
         ... )
-        [array([[1., 0., 0.],
-                [0., 0., 0.],
-                [1., 1., 1.]])]
+        [array([[0., 0., 0.],
+                [1., 0., 0.],
+                [1., 0., 0.]])]
 
         Alternatively, it is possible to calculate an expectation value if a classical
         processing function is provided that will accept the reconstructed circuit bitstrings
@@ -1252,7 +1254,7 @@ def fn(x):
         ...     shots,
         ...     fn
         ... )
-        array(4.)
+        array(-4.)
     """
     # pylint: disable=unused-argument, too-many-arguments
 


Test patch: