K iedZddlZddlmZddlmZddlmZddlm Z ddl m Z ddl m Z dd lmZdd lmZdd lmZdd lmZmZdd lmZddlmZddlmZmZmZddlm Z ddl!m"Z"ddl#m$Z$m%Z%ddl&m'Z'gdZ(GddeZ)Gdde)eZ*Gdde)eZ+Gdde)Z,Gdde,e*Z-Gdd e,e+Z.d!Z/d"Z0d)d#Z1d*d$Z2d*d%Z3d)d&Z4d'Z5d)d(Z6y)+zQubits for quantum computing. Todo: * Finish implementing measurement logic. This should include POVM. * Update docstrings. * Update tests. N)Add)Mul)Integer)Pow)S) conjugate)log_sympify) SYMPY_INTS)Matrixzeros) prettyForm) ComplexSpace)KetBraState) QuantumError represent) numpy_ndarrayscipy_sparse_matrix)bitcount) QubitQubitBraIntQubit IntQubitBraqubit_to_matrixmatrix_to_qubitmatrix_to_density measure_allmeasure_partialmeasure_partial_oneshotmeasure_all_oneshotcreZdZdZedZedZedZedZ edZ dZ dZ d Z y ) QubitStatez"Base class for Qubit and QubitBra.ct|dk(r"t|dtr|djSt|dk(r)t|dtrt d|dD}nt d|D}t d|D}|D]2}|t jt jfvs&td|z|S)Nrc3fK|])}|dk(rtjntj+yw)0NrZeroOne.0qbs a/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/physics/quantum/qubit.py z(QubitState._eval_args..Es#KRB#I!&&1558Ks/1c3tK|]0}|dk(rtjn|dk(rtjn|2yw)r*1Nr+r.s r1r2z(QubitState._eval_args..Gs,]RTB#I!&&B#I1552M]s68c32K|]}t|ywNr )r/args r1r2z(QubitState._eval_args..Hs3sXc]3z$Qubit values must be 0 or 1, got: %r) len isinstancer& qubit_valuesstrtuplerr,r- ValueError)clsargselements r1 _eval_argszQubitState._eval_args<s t9>ja*=7'' ' t9>ja#6K47KKD]X\]]D3d33 FGqvvquuo- :WDFF F c0tdt|zS)N)rr9)r?r@s r1_eval_hilbert_spacezQubitState._eval_hilbert_spaceQsAD ))rCc,t|jS)z"The number of Qubits in the state.)r9r;selfs r1 dimensionzQubitState.dimensionYs4$$%%rCc|jSr6rJrHs r1nqubitszQubitState.nqubits^s ~~rCc|jS)z,Returns the values of the qubits as a tuple.)labelrHs r1r;zQubitState.qubit_valuesbszzrCc|jSr6rLrHs r1__len__zQubitState.__len__ks ~~rCcR|jt|j|z dz S)Nr()r;intrJ)rIbits r1 __getitem__zQubitState.__getitem__ns&  T^^c%9A%=!>??rCct|j}|D]0}t|j|z dz }||dk(rd||<,d||<2|jt |S)zFlip the bit(s) given.r(r)listr;rSrJ __class__r=)rIbitsnewargsirTs r1flipzQubitState.flipusnt(() !Adnnq(1,-Cs|q      ! t~~uW~..rCN)__name__ __module__ __qualname____doc__ classmethodrBrFpropertyrJrMr;rQrUr\rCr1r&r&5sy, (**&&@ /rCr&c>eZdZdZedZdZdZdZdZ dZ y) raA multi-qubit ket in the computational (z) basis. We use the normal convention that the least significant qubit is on the right, so ``|00001>`` has a 1 in the least significant qubit. Parameters ========== values : list, str The qubit values as a list of ints ([0,0,0,1,1,]) or a string ('011'). Examples ======== Create a qubit in a couple of different ways and look at their attributes: >>> from sympy.physics.quantum.qubit import Qubit >>> Qubit(0,0,0) |000> >>> q = Qubit('0101') >>> q |0101> >>> q.nqubits 4 >>> len(q) 4 >>> q.dimension 4 >>> q.qubit_values (0, 1, 0, 1) We can flip the value of an individual qubit: >>> q.flip(1) |0111> We can take the dagger of a Qubit to get a bra: >>> from sympy.physics.quantum.dagger import Dagger >>> Dagger(q) <0101| >>> type(Dagger(q)) Inner products work as expected: >>> ip = Dagger(q)*q >>> ip <0101|0101> >>> ip.doit() 1 ctSr6)rrHs r1 dual_classzQubit.dual_classrCc t|j|jk(rtjStjSr6)rOrr-r,rIbrahintss r1_eval_innerproduct_QubitBraz!Qubit._eval_innerproduct_QubitBras$ :: "55L66MrCc &|jdi|S)Nr6)_represent_ZGate)rIoptionss r1_represent_default_basiszQubit._represent_default_basiss$t$$5W55rCc |jdd}d}d}t|jD]}|||zz }|dz}dgd|jzz}d|t |<|dk(r t |S|dk(r%ddl}|j|d jS|d k(r'dd l m } | j|d jSy) zBRepresent this qubits in the computational basis (ZGate). formatsympyr(rrEnumpyNcomplex)dtype scipy.sparse)sparse) getreversedr;rJrSr rtarray transposescipyrx csr_matrix) rIbasisro_formatndefinite_stateitresultnprxs r1rnzQubit._represent_ZGates++h0 4,,- B ad "N!A a'(&'s>"# g &> !   88F)84>>@ @  & $$$V9$=GGI I'rCc |jdg}t|}t|dk(rttd|j}|j ||z}tt|dz ddD] }|j |t||}"t||jk(r|dSt|S)Nindicesrr() ryrWr9rangerMsort_reduced_densityrSr )rIrjkwargsr sorted_idxnew_matr[s r1 _eval_tracezQubit._eval_traces**Y+'] z?a eAt||45Js(s:*B3 IA++GSA5GHG I  Ot|| +1: $W- -rCc (d}t|fi|}|j}|dz}tj|}t |D]J} t |D]:} t dD]*} || | |} || | |} || | fxx|| | fz cc<,<L|S)zCompute the reduced density matrix by tracing out one qubit. The qubit argument should be of type Python int, since it is used in bit operations c@d|zdz }||z d|zz||zz||zzS)NrEr(rc)jkqubitbit_masks r1find_index_that_is_projectedz.find_index_that_is_projecteds4%x!|H%ZQY/ALAQ%ZP PrCrE)rcolsr rr)rImatrixrror old_matrixold_sizenew_size new_matrixr[rrcolrows r1rzQubit._reduced_densitys  Qv11 ??Q;X^^H- x =A8_ =q=A6q!UCC6q!UCCq!t$ 38(<<$= = =rCN) r]r^r_r`rarfrlrprnrrrcrCr1rrs64l 6J(.,rCrc eZdZdZedZy)raA multi-qubit bra in the computational (z) basis. We use the normal convention that the least significant qubit is on the right, so ``|00001>`` has a 1 in the least significant qubit. Parameters ========== values : list, str The qubit values as a list of ints ([0,0,0,1,1,]) or a string ('011'). See also ======== Qubit: Examples using qubits ctSr6)rrHs r1rfzQubitBra.dual_classs rCNr]r^r_r`rarfrcrCr1rrs"rCrcLeZdZdZeddZedZdZdZdZ eZ eZ y) IntQubitStatez>A base class for qubits that work with binary representations.Nc t|dk(r(t|dtrtj|St d|Dst dt d|Dd|_t|ttfst dt|zt|dk7rt d|d |j|d|St|dk(r^|ddkDrVtttt|d}|Dcgc] }|d|z dz}}tj|St|d k(r |ddkDr|j|d|dStj|Scc}w) Nr(rc3HK|]}t|ttfywr6)r:rSrr/as r1r2z+IntQubitState._eval_args..(sAqZC>2As "zvalues must be integers, got (c32K|]}t|ywr6)typers r1r2z+IntQubitState._eval_args..)sI`VW$q'I`r8)z$nqubits must be an integer, got (%s)ztoo many positional arguments (z ). should be (number, nqubits=n)rE)r9r:r&rBallr>r=rSrr_eval_args_with_nqubitsrzrrabs)r?r@rMrvaluesr[r;s r1rBzIntQubitState._eval_args"sb t9>ja*=((. .ADAAEI`[_I`D`bc c  gW~6 !G$w-!WXX4yA~ [_acc..tAw@ @ t9>d1gkuXc$q'l%;<=G8?@1T!W\Q.@L@((6 6Y!^Q! ..tAwQ@ @((. .As E8ctt|}||krtd|d|dtt |Dcgc] }||z dz }}t j |Scc}w)Nzcannot represent z with z bitsr()rrr>rzrr&rB)r?numberrMneedr[r;s r1rz%IntQubitState._eval_args_with_nqubits@sjF $ T>6|j|g|}t|Sr6)rr)rIrr@rOs r1_print_label_prettyz!IntQubitState._print_label_prettyUs$!!!'1D1%  rCr6) r]r^r_r`rarBrrrr_print_label_repr_print_label_latexrcrCr1rrsHH//:33"!%%rCrc&eZdZdZedZdZy)raxA qubit ket that store integers as binary numbers in qubit values. The differences between this class and ``Qubit`` are: * The form of the constructor. * The qubit values are printed as their corresponding integer, rather than the raw qubit values. The internal storage format of the qubit values in the same as ``Qubit``. Parameters ========== values : int, tuple If a single argument, the integer we want to represent in the qubit values. This integer will be represented using the fewest possible number of qubits. If a pair of integers and the second value is more than one, the first integer gives the integer to represent in binary form and the second integer gives the number of qubits to use. List of zeros and ones is also accepted to generate qubit by bit pattern. nqubits : int The integer that represents the number of qubits. This number should be passed with keyword ``nqubits=N``. You can use this in order to avoid ambiguity of Qubit-style tuple of bits. Please see the example below for more details. Examples ======== Create a qubit for the integer 5: >>> from sympy.physics.quantum.qubit import IntQubit >>> from sympy.physics.quantum.qubit import Qubit >>> q = IntQubit(5) >>> q |5> We can also create an ``IntQubit`` by passing a ``Qubit`` instance. >>> q = IntQubit(Qubit('101')) >>> q |5> >>> q.as_int() 5 >>> q.nqubits 3 >>> q.qubit_values (1, 0, 1) We can go back to the regular qubit form. >>> Qubit(q) |101> Please note that ``IntQubit`` also accepts a ``Qubit``-style list of bits. So, the code below yields qubits 3, not a single bit ``1``. >>> IntQubit(1, 1) |3> To avoid ambiguity, use ``nqubits`` parameter. Use of this keyword is recommended especially when you provide the values by variables. >>> IntQubit(1, nqubits=1) |1> >>> a = 1 >>> IntQubit(a, nqubits=1) |1> ctSr6)rrHs r1rfzIntQubit.dual_classsrCc .tj||Sr6)rrlris r1_eval_innerproduct_IntQubitBraz'IntQubit._eval_innerproduct_IntQubitBras00s;;rCN)r]r^r_r`rarfrrcrCr1rr]s"EL>> from sympy.physics.quantum.qubit import matrix_to_qubit, Qubit >>> from sympy.physics.quantum.represent import represent >>> q = Qubit('01') >>> matrix_to_qubit(represent(q)) |01> rsrtrwrr(rEFTz*Matrix must be a row/column vector, got %rz>Matrix must be a row/column vector of size 2**nqubits, got: %r)rtrw)r:rrshaper rrrrrrurSreverserrrexpand) rrrmlistlenrMketr?rr[rAx qubit_arrays r1rrs*F&-(&-.||A!<<?h" aA <<?h" 86 A   gw '139:; ;F 8_ 8 QTlGQTlG . .g&G Ja3qAF|q01JKJ    !gc;&777F 8&3S/* MKs?E&c ddlm}|j}|Dcgc].}|dD]$}|ddk7rtt |g|dg&0}}}t |dk(rt jS||Scc}}w)z Works by finding the eigenvectors and eigenvalues of the matrix. We know we can decompose rho by doing: sum(EigenVal*|Eigenvect>>> from sympy.physics.quantum.qubit import Qubit, measure_all >>> from sympy.physics.quantum.gate import H >>> from sympy.physics.quantum.qapply import qapply >>> c = H(0)*H(1)*Qubit('00') >>> c H(0)*H(1)*|00> >>> q = qapply(c) >>> measure_all(q) [(|00>, 1/4), (|01>, 1/4), (|10>, 1/4), (|11>, 1/4)] rsrErM8This function cannot handle non-SymPy matrix formats yet) r normalizedmaxrrSmathr rappendrrrNotImplementedError)rrr normalizemresultssizerMr[s r1r!r!sD v&A   A177|dhhtnTXXa[01t At8Aw78!A$y1:NO  ! F  rCc~t||}t|ttfr t |f}|dk(r|r|j }t ||}g}|D]Y}d}||j|zdz }|dk7s |rt|j } n t|} |j| |f[|Std)aPerform a partial ensemble measure on the specified qubits. Parameters ========== qubits : Qubit The qubit to measure. This can be any Qubit or a linear combination of them. bits : tuple The qubits to measure. format : str The format of the intermediate matrices to use. Possible values are ('sympy','numpy','scipy.sparse'). Currently only 'sympy' is implemented. Returns ======= result : list A list that consists of primitive states and their probabilities. Examples ======== >>> from sympy.physics.quantum.qubit import Qubit, measure_partial >>> from sympy.physics.quantum.gate import H >>> from sympy.physics.quantum.qapply import qapply >>> c = H(0)*H(1)*Qubit('00') >>> c H(0)*H(1)*|00> >>> q = qapply(c) >>> measure_partial(q, (0,)) [(sqrt(2)*|00>/2 + sqrt(2)*|10>/2, 1/2), (sqrt(2)*|01>/2 + sqrt(2)*|11>/2, 1/2)] rsrr) rr:r rrSr_get_possible_outcomesHrrr) rrYrrrrpossible_outcomesoutputoutcomeprob_of_outcome next_matrixs r1r"r"TsH v&A$W-.D |   A21d;( G O  ' 115 5O!#"1'2D2D2F"GK"1'":K # & ! F  rCcddl}t||}|dk(rk|j}t||}|j}d}|D]7}||j|zdz }||k\st |jcSyt d)aPerform a partial oneshot measurement on the specified qubits. A oneshot measurement is equivalent to performing a measurement on a quantum system. This type of measurement does not return the probabilities like an ensemble measurement does, but rather returns *one* of the possible resulting states. The exact state that is returned is determined by picking a state randomly according to the ensemble probabilities. Parameters ---------- qubits : Qubit The qubit to measure. This can be any Qubit or a linear combination of them. bits : tuple The qubits to measure. format : str The format of the intermediate matrices to use. Possible values are ('sympy','numpy','scipy.sparse'). Currently only 'sympy' is implemented. Returns ------- result : Qubit The qubit that the system collapsed to upon measurement. rNrsr)randomrrrrrr) rrYrrrrr random_number total_probrs r1r#r#s4v&A  LLN21d;   ( =G 799W,a0 0J]*&w'9'9';<<  =" F  rCct|j}ttj|dz}g}t dt |zD] }|jtd|zd"g}|D]}|jd|zt d|zD]9}d}t t |D]} ||| zs || dzz }|||||<;|S)aGet the possible states that can be produced in a measurement. Parameters ---------- m : Matrix The matrix representing the state of the system. bits : tuple, list Which bits will be measured. Returns ------- result : list The list of possible states which can occur given this measurement. These are un-normalized so we can derive the probability of finding this state by taking the inner product with itself 皙?r(rEr) rrrSrlog2rr9rr) rrYrrMoutput_matricesr[ bit_masksrTtruenessrs r1rrs( qww "5uQZ345 I#c"#1g: ,s9~& "A9Q<AE! "()t!!$, rCc jddl}t|}|dk(r|j}|j}d}d}|D]$}|||jzz }||kDrn|dz }&t t |t tjt|jdzStd)adPerform a oneshot ensemble measurement on all qubits. A oneshot measurement is equivalent to performing a measurement on a quantum system. This type of measurement does not return the probabilities like an ensemble measurement does, but rather returns *one* of the possible resulting states. The exact state that is returned is determined by picking a state randomly according to the ensemble probabilities. Parameters ---------- qubits : Qubit The qubit to measure. This can be any Qubit or a linear combination of them. format : str The format of the intermediate matrices to use. Possible values are ('sympy','numpy','scipy.sparse'). Currently only 'sympy' is implemented. Returns ------- result : Qubit The qubit that the system collapsed to upon measurement. rNrsr(rrr) rrrrrrrSrrrrr)rrrrrrtotalrr[s r1r$r$s0A  LLN   A Qq{{}_ $E}$ aKF   Xfc$))CL2IB2N.OPQQ! F  rC)rs)rsT)7r`rsympy.core.addrsympy.core.mulrsympy.core.numbersrsympy.core.powerrsympy.core.singletonr$sympy.functions.elementary.complexesr&sympy.functions.elementary.exponentialr sympy.core.basicr sympy.external.gmpyr sympy.matricesr r sympy.printing.pretty.stringpictrsympy.physics.quantum.hilbertrsympy.physics.quantum.staterrrsympy.physics.quantum.qexprrsympy.physics.quantum.representr!sympy.physics.quantum.matrixutilsrrmpmath.libmp.libintmathr__all__r&rrrrrrr rr!r"r#rr$rcrCr1rs & ":6%*(767745- &I/I/XDJDNz3.;&J;&|L<}eL<\-CL  +5 pH V- `0f) rC