Repository: qiskit-community/prototype-zne (language: python)

Issue:
Allow bypassing ZNE functionality from `run()`
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues to confirm this idea does not exist. -->

### What is the expected enhancement?
<!-- Please, provide a clear and concise description of the expected behavior for this enhancement. -->
With the current implementation, a default `zne_strategy` can be configured on `__init__()`, or by accessing the object's attribute by the same name. If that is the case, when `zne_strategy=None` is provided in `run()` the default will apply. 

If said default is equivalent to applying no ZNE this is a way of bypassing the functionality, but, if it is not, then we would need to provide a no-op `zne_strategy` to achieve this behavior; which can be cumbersome.

This enhancement consists on bypassing the ZNE functionality in a simpler way. Additionally, we suggest adding a `noop()` class method to `ZNEStrategy` in order to quickly build a no-op `zne_strategy` object.


Discussion / hints:

Fix patch:
diff --git a/zne/meta/cls.py b/zne/meta/cls.py
index b935f37..2487b59 100644
--- a/zne/meta/cls.py
+++ b/zne/meta/cls.py
@@ -55,7 +55,7 @@ def _get_zne_strategy(self) -> ZNEStrategy:
 
 def _set_zne_strategy(self, zne_strategy: ZNEStrategy | None) -> None:
     if zne_strategy is None:
-        zne_strategy = ZNEStrategy(noise_factors=(1,))
+        zne_strategy = ZNEStrategy.noop()
     elif not isinstance(zne_strategy, ZNEStrategy):
         raise TypeError("Invalid zne_strategy object, expected ZNEStrategy.")
     self._zne_strategy = zne_strategy  # pylint: disable=protected-access
diff --git a/zne/zne_strategy.py b/zne/zne_strategy.py
index 0e7aa84..ba39d62 100644
--- a/zne/zne_strategy.py
+++ b/zne/zne_strategy.py
@@ -73,12 +73,20 @@ class ZNEStrategy:
         FrozenInstanceError: On attempt to update any data field.
     """
 
-    noise_amplifier: NoiseAmplifier = CxAmplifier()
     noise_factors: Sequence[float] = (1,)
+    noise_amplifier: NoiseAmplifier = CxAmplifier()
     extrapolator: Extrapolator = LinearExtrapolator()
     transpilation_level: int | None = 1
     transpiler: PassManager | None = None
 
+    ################################################################################
+    ## NEW
+    ################################################################################
+    @classmethod
+    def noop(cls) -> ZNEStrategy:
+        """Construct a no-op ZNE strategy object."""
+        return cls(noise_factors=(1,))
+
     ################################################################################
     ## INIT
     ################################################################################


Test patch:
diff --git a/test/test_zne_strategy.py b/test/test_zne_strategy.py
index 07b7786..bebe6d3 100644
--- a/test/test_zne_strategy.py
+++ b/test/test_zne_strategy.py
@@ -50,9 +50,15 @@ def infer(target, data):
         return extrapolator
 
     ################################################################################
-    ## INIT
+    ## NEW
     ################################################################################
+    def test_noop(self):
+        zne_strategy = ZNEStrategy.noop()
+        assert zne_strategy.noise_factors == (1,)  # No-op condition
 
+    ################################################################################
+    ## INIT
+    ################################################################################
     def test_defaults(self):
         DEFAULT_NOISE_AMPLIFIER = CxAmplifier()
         DEFAULT_NOISE_FACTORS = (1,)