
    i*                        S r SSKJr  SSKJrJr  SSKJr  SSKJ	r	  SSK
Jr  SSKJr  SSKJr  SS	KJrJr  SS
KJr   SSKJr  SSKJr  Sr " S S5      rg! \ a    Sr Nf = f)zFA class to help understand the expected performance of estimator jobs.    )annotations)OptionalSequence)QiskitError)PassManager)EstimatorPubLike)EstimatorPub)	BackendV2)NeatPubResult
NeatResult)ConvertISAToClifford)
NoiseModel)EstimatorV2TFc                      \ rS rSrSrSSS jjr\SS j5       r\R                  SS j5       rSS jr	 S           SS jjr
   S         SS	 jjr   S         SS
 jjrSS jrSS jrSrg)Neat%   a9  A class to help understand the expected performance of estimator jobs.

The "Noisy Estimator Analyzer Tool" (or "NEAT") is a convenience tool that users of the
:class:`~.Estimator` primitive can employ to analyze and predict the performance of
their queries. Its simulate method uses ``qiskit-aer`` to simulate the estimation task
classically efficiently, either in ideal conditions or in the presence of noise. The
simulations' results can be compared with other simulation results or with primitive results
results to draw custom figures of merit.

.. code::python

    # Initialize a Neat object
    analyzer = Neat(backend)

    # Map arbitrary PUBs to Clifford PUBs
    cliff_pubs = analyzer.to_clifford(pubs)

    # Calculate the expectation values in the absence of noise
    r_ideal = analyzer.ideal_sim(cliff_pubs)

    # Calculate the expectation values in the presence of noise
    r_noisy = analyzer.noisy_sim(cliff_pubs)

    # Calculate the expectation values for a different noise model
    analyzer.noise_model = another_noise_model
    another_r_noisy = analyzer.noisy_sim(cliff_pubs)

    # Run the Clifford PUBs on a QPU
    r_qpu = estimator.run(cliff_pubs)

    # Calculate useful figures of merit using mathematical operators, for example the relative
    # difference between experimental and noisy results, ...
    rel_diff = abs(r_noisy[0] - r_qpu[0]) / r_noisy[0]

    # ... the signal-to-noise ratio between experimental and ideal results, ...
    ratio = r_qpu[0] / r_ideal[0]

    # ... or the absolute difference between results obtained with different noise models
    abs_diff = abs(r_noisy[0] - another_r_noisy[0])

Args:
    backend: A backend.
    noise_model: A noise model for the operations of the given backend. If ``None``, it
        defaults to the noise model generated by :meth:`NoiseModel.from_backend`.
Nc                    [         (       d  [        S5      eXl        Ub  UU l        g [        R                  " USS9U l        g )NzpCannot initialize object of type 'Neat' since 'qiskit-aer' is not installed. Install 'qiskit-aer' and try again.F)thermal_relaxation)HAS_QISKIT_AER
ValueError_backendr   from_backendnoise_model)selfbackendr   s      ]/home/james-whalen/.local/lib/python3.13/site-packages/qiskit_ibm_runtime/debug_tools/neat.py__init__Neat.__init__T   sO    ~6 
   &  	 ((UK 	    c                    U R                   $ )zG
The noise model used by this analyzer tool for the noisy simulations.
_noise_modelr   s    r   r   Neat.noise_modelb   s    
    r   c                    Xl         g)z=Sets a new noise model.

Args:
    value: A new noise model.
Nr!   )r   values     r   r   r$   i   s
     "r   c                    U R                   $ )z)
The backend used by this analyzer tool.
)r   r#   s    r   r   Neat.backendr   s     }}r   c                   U(       a  U R                  U5      nO&U Vs/ s H  n[        R                  " U5      PM     nnSU(       a  U R                  OSUS.n[	        XS.S9n	U	R                  U5      n
 U
R                  5       nU Vs/ s H"  n[        UR                  R                  5      PM$     nn[        U5      $ s  snf ! [         a"  nS[        U5      ;   a  [        S5      UeUeSnAff = fs  snf )a  
Perform a noisy or noiseless simulation of the estimator task specified by ``pubs``.

Args:
    pubs: The PUBs specifying the estimation task of interest.
    with_noise: Whether to perform an ideal, noiseless simulation (``False``) or a noisy
        simulation (``True``).
    cliffordize: Whether or not to automatically apply the
        :class:`.~ConvertISAToClifford` transpiler pass to the given ``pubs`` before
        performing the simulations.
    seed_simulator: A seed for the simulator.
    precision: The target precision for the estimates of each expectation value in the
        returned results.

Returns:
    The results of the simulation.

stabilizerN)methodr   seed_simulator)backend_optionsdefault_precision)optionszinvalid parameterszCouldn't run the simulation, likely because the given PUBs contain one or more non-Clifford instructions. To fix, try setting ``cliffordize`` to ``True``.)to_cliffordr	   coercer   AerEstimatorrunresultr   strr   r   dataevsr   )r   pubs
with_noisecliffordizer,   	precisioncoerced_pubspr-   	estimatoraer_job
aer_resulterrrpub_resultss                  r   	_simulateNeat._simulatex   s    2 ++D1L<@ADqL//2DLA #/94++t,

 !(7X
	 ---		 )J ;EE*Q}QVVZZ0*E+&&1 B  	#s3x/   	
 I	 Fs#    C 6C 
)C4
C1C,,C1c                *    U R                  USX#U5      $ )a  
Perform an ideal, noiseless simulation of the estimator task specified by ``pubs``.

This function uses ``qiskit-aer``'s ``Estimator`` class to simulate the estimation task
classically.

.. note::
    To ensure scalability, every circuit in ``pubs`` is required to be a Clifford circuit,
    so that it can be simulated efficiently regardless of its size. For estimation tasks
    that involve non-Clifford circuits, the recommended workflow consists of mapping
    the non-Clifford circuits to the nearest Clifford circuits using the
    :class:`.~ConvertISAToClifford` transpiler pass, or equivalently, to use the Neat's
    :meth:`to_clifford` convenience method. Alternatively, setting ``cliffordize`` to
    ``True`` ensures that the :meth:`to_clifford` method is applied automatically to the
    given ``pubs`` prior to the simulation.

Args:
    pubs: The PUBs specifying the estimation task of interest.
    cliffordize: Whether or not to automatically apply the
        :class:`.~ConvertISAToClifford` transpiler pass to the given ``pubs`` before
        performing the simulations.
    seed_simulator: A seed for the simulator.
    precision: The target precision for the estimates of each expectation value in the
        returned results.

Returns:
    The results of the simulation.
FrD   r   r8   r:   r,   r;   s        r   	ideal_simNeat.ideal_sim   s    F ~~dE;	RRr   c                *    U R                  USX#U5      $ )a  
Perform a noisy simulation of the estimator task specified by ``pubs``.

This function uses ``qiskit-aer``'s ``Estimator`` class to simulate the estimation task
classically.

.. note::
    To ensure scalability, every circuit in ``pubs`` is required to be a Clifford circuit,
    so that it can be simulated efficiently regardless of its size. For estimation tasks
    that involve non-Clifford circuits, the recommended workflow consists of mapping
    the non-Clifford circuits to the nearest Clifford circuits using the
    :class:`.~ConvertISAToClifford` transpiler pass, or equivalently, to use the Neat's
    :meth:`to_clifford` convenience method. Alternatively, setting ``cliffordize`` to
    ``True`` ensures that the :meth:`to_clifford` method is applied automatically to the
    given ``pubs`` prior to the simulation.

Args:
    pubs: The PUBs specifying the estimation task of interest.
    cliffordize: Whether or not to automatically apply the
        :class:`.~ConvertISAToClifford` transpiler pass to the given ``pubs`` before
        performing the simulations.
    seed_simulator: A seed for the simulator.
    precision: The target precision for the estimates of each expectation value in the
        returned results.

Returns:
    The results of the simulation.
TrG   rH   s        r   	noisy_simNeat.noisy_sim   s    F ~~dD+yQQr   c           
        / nU H  n[         R                  " U5      nUR                  [        [        [	        5       /5      R                  UR                  5      UR                  UR                  UR                  S5      5        M     U$ )z
Return the cliffordized version of the given ``pubs``.

This convenience method runs the :class:`.~ConvertISAToClifford` transpiler pass on the
PUBs' circuits.

Args:
    pubs: The PUBs to turn into Clifford PUBs.

Returns:
    The Clifford PUBs.
F)
r	   r1   appendr   r   r3   circuitobservablesparameter_valuesr;   )r   r8   r<   pubcoerced_pubs        r   r0   Neat.to_clifford   s     C&--c2K!5!7 89==k>Q>QR++00))  r   c                >    SU R                  5       R                   S3$ )NzNeat(backend="z"))r   namer#   s    r   __repr__Neat.__repr__  s     3 34B77r   )r   r"   r   )N)r   Backendr   zOptional[NoiseModel]returnNone)r[   r   )r&   r   r[   r   )r[   rZ   )r   )r8   Sequence[EstimatorPubLike]r9   boolr:   r^   r,   Optional[int]r;   floatr[   r   )FNr   )
r8   r]   r:   r^   r,   r_   r;   r`   r[   r   )r8   r]   r[   zlist[EstimatorPub])r[   r5   )__name__
__module____qualname____firstlineno____doc__r   propertyr   setterr   rD   rI   rL   r0   rX   __static_attributes__ r   r   r   r   %   s   ,\
 ! ! " " 4'(4' 4' 	4'
 &4' 4' 
4'r "(,#S(#S #S &	#S
 #S 
#SP "(,#R(#R #R &	#R
 #R 
#RJ88r   r   N)re   
__future__r   typingr   r   qiskit.exceptionsr   qiskit.transpiler.passmanagerr   qiskit.primitives.containersr   *qiskit.primitives.containers.estimator_pubr	   qiskit.providersr
   rZ   +qiskit_ibm_runtime.debug_tools.neat_resultsr   r   4qiskit_ibm_runtime.transpiler.passes.cliffordizationr   qiskit_aer.noiser   "qiskit_aer.primitives.estimator_v2r   r2   r   ImportErrorr   ri   r   r   <module>rv      sX    M " % ) 5 9 C 1 Q U+NN
p8 p8	  Ns   A A"!A"