
    z	i:              	         S r SSKJr  SSKJr  SSKJrJr  SSK	J
r
JrJrJr  SSKrSSKJr  SSKJrJrJrJr  S	S
KJr  S	SKJrJr  \(       a  SSKJr  SS/r\
\\S4   r\
\ \\\\\
\ \4   \!4   4   r" \
\"\4   r#  " S S\5      r$g)z5
ND-Array container class for Estimator observables.
    )annotationsdeepcopy)IterableMapping)Unionr   overloadTYPE_CHECKINGN)	ArrayLike)Pauli	PauliListSparsePauliOpSparseObservable   )object_array)ShapedMixinshape_tuple)TranspileLayoutObservableLikeObservablesArrayLikec                  l  ^  \ rS rSrSrSr   S       SU 4S jjjr\SS j5       rS r	SS jr
SSS jjrS S!S	 jjr\S"S
 j5       r\S#S j5       rS r\S$S j5       r\S#S j5       rS rS%S jrS&S jr\S'S j5       r\S(S j5       r\S)S j5       rS*S+S jjrS r S,     S-S jjrS rSrU =r$ ).ObservablesArray7   zJAn ND-array of Hermitian observables for an :class:`.Estimator` primitive.)_array_shapec                  > [         TU ]  5         [        U[        5      (       a  UR                  n[        X[        4S9U l        U R                  R                  U l        X l	        U(       a  [        R                  " U R                  5       Hh  u  pVU R                  U5      nU R                  c  UR                  U l	        O%U R                  UR                  :w  a  [        S5      eXpR                  U'   Mj     OTU R                  cG  U R                  R                  S:  a-  U R                  R!                  S5      S   R                  U l	        U R                  c  SU l	        gg)a  Initialize an observables array.

Args:
    observables: An array-like of basis observable compatible objects.
    copy: Specify the ``copy`` kwarg of the :func:`.object_array` function
        when initializing observables.
    num_qubits: The number of qubits of the observables. If not specified, the number of
        qubits will be inferred from the observables. If specified, then the specified
        number of qubits must match the number of qubits in the observables.
    validate: If true, coerce entries into the internal format and validate them. If false,
        the input should already be an array-like.

Raises:
    ValueError: If ``validate=True`` and the input observables array is not valid.
)copy
list_typesNzSThe number of qubits must be the same for all observables in the observables array.r   )super__init__
isinstancer   r   r   r   shaper   _num_qubitsnpndenumeratecoerce_observable
num_qubits
ValueErrorsizereshape)	selfobservablesr(   r   validatendiobs	basis_obs	__class__s	           h/home/james-whalen/.local/lib/python3.13/site-packages/qiskit/primitives/containers/observables_array.pyr!   ObservablesArray.__init__<   s&   , 	k#344%,,K";ylSkk''%NN4;;7 2237	##+'0';';D$%%)=)==$-  $-C  8 %$++*:*:Q*>#{{2226q9DDD # D $    c                   0 nU R                  5        H  u  p#n[        U5      S:X  a  SU R                  -  nO[        [	        X25      5      n/ nSnU H#  u  pUR                  SX-
  S-
  -  U
-   5        U	nM%     UR                  SU R                  [        U5      -
  S-
  -  5        SR                  U5      SSS2   n[        R                  " U5      X'   M     U$ )zWConvert a simplified sparse observable to a mapping from Pauli strings to coefficients.r   Ir   r    N)
to_sparse_listlenr(   sortedzipappendmaxjoinr%   real)r0   resultsparse_pauli_strpauli_qubitscoefffull_pauli_strsorted_listsstring_fragments
prev_qubitqubitpaulis              r3   _obs_to_dictObservablesArray._obs_to_dictk   s     585G5G5I1E#$)!$s~~!5%c,&IJ#% 
$0LE$++C53E3I,JU,RS!&J %1 !''s~~L@Q/QTU/U(VW!#)9!:4R4!@ &(WWU^F"# 6J& r5   c                    [        U 5      R                   S3nSU R                   S3n[        R                  " U R                  5       XSS9nX-   U-   $ )N(z, shape=)2   )prefixsuffix	threshold)type__name__r#   r%   array2string	__array__)r,   rQ   rR   arrays       r3   __repr__ObservablesArray.__repr__   sR    J''(*DJJ<q) 0Z\]~&&r5   c                >    U R                  5       R                  5       $ )a  Convert to a nested list.

Similar to Numpy's ``tolist`` method, the level of nesting
depends on the dimension of the observables array. In the
case of dimension 0 the method returns a single observable
(``dict`` in the case of a weighted sum of Paulis) instead of a list.

Examples::
    Return values for a one-element list vs one element:

        >>> from qiskit.primitives.containers.observables_array import ObservablesArray
        >>> oa = ObservablesArray.coerce(["Z"])
        >>> print(type(oa.tolist()))
        <class 'list'>
        >>> oa = ObservablesArray.coerce("Z")
        >>> print(type(oa.tolist()))
        <class 'dict'>
)rW   tolistr,   s    r3   r\   ObservablesArray.tolist   s    & ~~&&((r5   c                
   Ub
  U[         :X  a  U R                  [        S U R                  R                   5       5      5      n[        U R                  R                  5      S:X  a3  [        R                  " U R                  R                  [        S9nX4S'   U$ [        R                  " UR                  [        S9n[        R                  " UR                  5       H  u  pVU R                  U5      XE'   M     U$ [        S5      e)z6Convert to a Numpy.ndarray with elements of type dict.c              3  8   #    U  H  n[        S 5      v   M     g 7fN)slice).0_s     r3   	<genexpr>-ObservablesArray.__array__.<locals>.<genexpr>   s     /WEVdEVs   r   )r#   dtype rg   zType must be 'None' or 'object')object__getitem__tupler   r#   r:   r%   ndarraydictr&   rK   r)   )r,   rg   r   
tmp_resultrA   r/   r0   s          r3   rW   ObservablesArray.__array__   s    =EVO))%/WT[[EVEV/W*WXJ4;;$$%*$++*;*;4H'r

 M J$4$4DA "z/@/@ AHC"&"3"3C"8FK !BM:;;r5   c                d    U(       a  U R                  5       nUR                  $ U nUR                  $ )a  Convert to a :class:`numpy.ndarray` with elements of type :class:`~.SparseObservable`.

Args:
    copy: Whether to make a new array instance with new sparse observables as elements.

Returns:
    A :class:`numpy.ndarray` with elements of type :class:`~.SparseObservable`.
)r   r   )r,   r   r0   s      r3   sparse_observables_array)ObservablesArray.sparse_observables_array   s,     "diikzz (,zzr5   c                    g ra   rh   r,   argss     r3   rk   ObservablesArray.__getitem__   s    ORr5   c                    g ra   rh   ru   s     r3   rk   rw      s    X[r5   c                    U R                   U   n[        U[        R                  5      (       d  U R	                  U5      $ [        USSS9$ )NFr   r.   )r   r"   r%   rm   rK   r   r,   rv   items      r3   rk   rw      sA    {{4 $

++$$T**55AAr5   c                    g ra   rh   ru   s     r3   rb   ObservablesArray.slice   s    FIr5   c                    g ra   rh   ru   s     r3   rb   r~      s    RUr5   c                x    U R                   U   n[        U[        R                  5      (       d  U$ [	        USSS9$ )a7  Take a slice of the observables in this array.

.. note::
   This method does not copy observables; modifying the returned observables will affect this
   instance.

Returns:
    A single :class:`~.SparseObservable` if an integer is given for every array axis, otherwise,
    a new :class:`~.ObservablesArray`.
Frz   )r   r"   r%   rm   r   r{   s      r3   rb   r~      s7     {{4 $

++K55AAr5   c                Z    [        U6 n[        U R                  R                  U5      SSS9$ )zReturn a new array with a different shape.

This results in a new view of the same arrays.

Args:
    shape: The shape of the returned array.

Returns:
    A new array.
Frz   )r   r   r   r+   )r,   r#   s     r3   r+   ObservablesArray.reshape   s-     U# 3 3E :QVWWr5   c                8    U R                  U R                  5      $ )zReturn a new array with one dimension.

The returned array has a :attr:`shape` given by ``(size, )``, where
the size is the :attr:`~size` of this array.

Returns:
    A new flattened array.
)r+   r*   r]   s    r3   ravelObservablesArray.ravel   s     ||DII&&r5   c                    U R                   $ )z-The number of qubits each observable acts on.)r$   r]   s    r3   r(   ObservablesArray.num_qubits   s     r5   c                   [        U[        5      (       a  [        R                  " U5      nGO5[        U[        5      (       a  [        R
                  " U5      nGO[        U[        5      (       a  [        R                  " U5      nO[        U[        5      (       a  / nUR                  5        H  u  p4[        U[        5      (       a  UR                  X445        M.  [        U[        5      (       aC  USS R                  5       UR                  peUR                  U[        SS5      U-  U-  45        M  [        S[        U5       35      e   [        R                   " U5      n[        U[        5      (       a  UR#                  5       n[$        R&                  " UR(                  5      n[$        R*                  " U5      (       a  [-        S5      e[        R.                  " UR0                  UUR2                  UR4                  UR6                  5      nU[        R8                  " UR0                  5      :X  a  [-        S5      eU$ [        S[        U5       35      e)a,  Format an observable-like object into the internal format.

Args:
    observable: The observable-like to format.

Returns:
    The coerced observable.

Raises:
    TypeError: If the input cannot be formatted because its type is not valid.
    ValueError: If the input observable is invalid or empty.
Nr   r   zInvalid observable basis type: zrNon-Hermitian input observable: the simplified input observable has a non-zero imaginary part in its coefficients.zEmpty observable was detected.zInvalid observable type: )r"   r   r   from_sparse_pauli_opr   
from_paulistr
from_label_Mappingitemsr=   to_labelphasecomplex	TypeErrorrT   	from_listsimplifyr%   real_if_closecoeffsiscomplexobjr)   from_raw_partsr(   	bit_termsindices
boundarieszero)cls
observable	term_listbasisrD   unphased_basisr   r   s           r3   r'   "ObservablesArray.coerce_observable   s    j-00)>>zJJ
E**)44Z@J
C(()44Z@J
H--I * 0 0 2eS))$$e^4u--,1!H,=,=,?E$$ngamu6Lu6T%UV#&Ed5k]$STT !3 *33I>Jj"233#,,.J %%j&7&78Fv&& ; 
 *88%%$$""%%J -22:3H3HII !ABB3D4D3EFGGr5   c                @    [        U[        5      (       a  U$ U " U5      $ )zCoerce ObservablesArrayLike into ObservableArray.

Args:
    observables: an object to be observables array.

Returns:
    A coerced observables array.
)r"   r   )r   r-   s     r3   coerceObservablesArray.coerce6  s#     k#344;r5   c                j   U R                   UR                   :w  d  U R                  UR                  :w  a  g[        R                  " U R                   5      n[	        U R
                  R                  5       UR
                  R                  5       5       H  u  pEXE-
  R                  U5      U:w  d  M    g   g)at  Compute whether the observable arrays are equal within a given tolerance.

Args:
    other: Another observables array to compare with.
    tol: The tolerance to provide to :attr:`~.SparseObservable.simplify` during checking.

Returns:
    Whether the two observables arrays have the same shape and number of qubits,
    and if so, whether they are equal within tolerance.
FT)r(   r#   r   r   r<   r   r   r   )r,   othertolzero_obsobs1obs2s         r3   
equivalentObservablesArray.equivalentD  s     ??e...$**2K#((9dkk//15<<3E3E3GHJD%%c*h6 I r5   c                    [        U 5      $ )z Return a deep copy of the array.r   r]   s    r3   r   ObservablesArray.copyY  s    ~r5   c                    Uc  Uc  U R                  5       $ [        R                  " U R                  [        S9n[        R
                  " U R                  5       H  u  pEUR                  X5      X4'   M     [        USS9$ )a  Apply a transpiler layout to this :class:`~.ObservablesArray`.

Args:
    layout: Either a :class:`~.TranspileLayout`, a list of integers or None.
            If both layout and ``num_qubits`` are none, a deep copy of the array is
            returned.
    num_qubits: The number of qubits to expand the array to. If not
        provided then if ``layout`` is a :class:`~.TranspileLayout` the
        number of the transpiler output circuit qubits will be used by
        default. If ``layout`` is a list of integers the permutation
        specified will be applied without any expansion. If layout is
        None, the array will be expanded to the given number of qubits.

Returns:
    A new :class:`.ObservablesArray` with the provided layout applied.

Raises:
    QiskitError: ...
ri   F)r.   )	r   r%   rm   r#   r   r&   r   apply_layoutr   )r,   layoutr(   new_arrr/   r0   s         r3   r   ObservablesArray.apply_layout]  si    , >j099;**TZZ/?@t{{3HC++F?GL 4  %88r5   c                    U R                   R                  S5       H(  nUR                  U R                  :w  d  M  [        S5      e   g)z.Validate the consistency in observables array.r   z^An observable was detected, whose number of qubits does not match the array's number of qubitsN)r   r+   r(   r)   )r,   r0   s     r3   r.   ObservablesArray.validate|  s>    ;;&&r*C~~0 C  +r5   )r   r$   r   )NTT)r-   r   r(   
int | Noner   boolr.   r   )r0   r   returnMapping[str, float])r   zlist | ObservableLike)NN)r   
np.ndarray)F)r   r   r   r   )rv   int | tuple[int, ...]r   r   )rv   z!IndexType | tuple[IndexType, ...]r   r   )rv   r   r   r   )r#   zint | Iterable[int]r   r   )r   r   )r   int)r   r   r   r   )r-   r   r   r   )g:0yE>)r   r   r   floatr   r   ra   )r   z"TranspileLayout | list[int] | Noner(   r   r   r   )rU   
__module____qualname____firstlineno____doc__	__slots__r!   staticmethodrK   rY   r\   rW   rr   r	   rk   rb   r+   r   propertyr(   classmethodr'   r   r   r   r   r.   __static_attributes____classcell__)r2   s   @r3   r   r   7   s9   T$I
 "&-!)-! -! 	-!
 -! -!^  0')*<
 R R[ [B I IU UB"X	'     8H 8Ht    *
 TX989FP9	9> r5   r   )%r   
__future__r   r   r   collections.abcr   r   r   typingr   r	   r
   numpyr%   numpy.typingr   qiskit.quantum_infor   r   r   r   r   r#   r   r   qiskit.transpiler.layoutr   __all__r   rb   	IndexTyper   r   r   r   r   rh   r5   r3   <module>r      s    #  9 : :  " Q Q & + 8 3
4#ud"#		E#u*u$%	' U ^Y67  ZL{ Lr5   