
    z	iEy                        S r SSKrSSKJr  SSKJrJrJr  SSKJ	r	  SSK
Jr  SSKJr  SSKJrJr  \R"                  S	S4\R$                  S	S4\R&                  S	S4\R(                  S	S	4\R*                  S	S
4\R,                  S	S4\R.                  S	S	4\R0                  S	S	4\R2                  S	S	4\R4                  S	S4\R6                  S	S4\R8                  S	S4\R:                  S	S4\R<                  S	S4\R>                  S	S4\R@                  S	S	4\RB                  S	S
4\RD                  S	S4\RF                  S	S4\RH                  S	S4/r%\RL                  S
S4\RN                  S
S4\RP                  S
S4\RR                  S
S	4\RT                  S
S	4\RV                  S
S	4\RX                  S
S	4\RZ                  S
S4\R\                  S
S4\R^                  S
S	4\R`                  S
S4\Rb                  S
S4\Rd                  S
S4\Rf                  S
S	4\Rh                  S
S	4\Rj                  S
S	4\Rl                  S
S	4\Rn                  S
S
4\Rp                  S
S
4\Rr                  S
S4\Rt                  S
S4\Rv                  S
S4\Rx                  S
S4\Rz                  S
S4/r>         SS jr?      SS\@4S jjrASS jrBg)z1Utility functions for generating random circuits.    N)	PyDiGraph)ClassicalRegisterQuantumCircuitCircuitInstruction)Reset)standard_gates)CircuitError)	_BASIS_1Q	_BASIS_2Q            c
           
      t   US;  a  [        S5      eUS:X  a  U(       d  [        S5      eSn
SnSnSn[        U [        5      (       a  [        U 5      n/ n/ nU  H9  u  pnUR	                  X45        UR	                  U5        X:  a  Un
X:  d  M7  Un
M;     U
S-  n
[
        R                  " U5      n[
        R                  " U5      nO[        U [        5      (       ai  U R                  5       n
U R                  5       n[
        R                  " U R                  5       5      n[
        R                  " U R                  5       5      nO[        S5      eU
S:X  a
  [        5       $ X:  a  UOU
nUS:X  a  U(       d  [        S5      eUS:X  d  US:X  a  [        U
USUUUUS	9$ SU;   a  US:g  nUU   nUU   n[        U5      n[        U5      (       aK  U H  nUS:  d  M  [        S
5      e   UR!                  5       n[
        R"                  " USSS9(       d  UU-  nO:[%        U5      (       a  [        S5      eSU;   a  [
        R&                  " U5      U-  n[
        R                  " [(        S[*        4S[
        R,                  4S[
        R,                  4/S9nU(       a#  [
        R                  " [.        UR0                  S9n[        U
5      nU(       d  U(       a  [3        U
S5      nUR5                  U5        UcL  [
        R6                  R9                  S[
        R:                  " [
        R<                  5      R>                  5      n[
        R6                  RA                  U5      n[
        R                  " URB                  [*        SS9nU Vs0 s H  n[E        U5      S_M     nnSnSnSnU(       d2  [
        RF                  " U
[H        S9n[
        RF                  " U[H        S9nU(       d  [
        RF                  " U[H        S9nU(       Ga  [K        [M        U
5      5      n URO                  UUSUS9n!URO                  UUSS9n"[
        RP                  " U"S   [
        R,                  S9n#URS                  SS[
        RT                  -  U#S   S9n$U(       a  UR7                  US4S9U	:  nU(       aO  UR7                  [        U"5      S9U:  nURW                  SS[Y        U
S5      -  [
        RZ                  " U5      S9nSn%[]        U"S   U"S   U!WU5       GHO  u  n&n'nn(n)[E        U5      u  n*n+U(       aW  U)u  n,n-[_        5       n.U,(       a  URa                  [c        U.UU*   /S95        U-(       a  URa                  [c        U.UU+   /S95        U$SU' n/U$U'S n$U&" U/6 n0U((       ak  URe                  URB                  W5        URg                  U[i        UW%   5      45         U%S-  n%UR	                  [c        U0UU*   UU+   /S95        SSS5        O!URa                  [c        U0UU*   UU+   /S95        U [K        U5      -
  n U*U+4n1U1U;   d  GM3  UU1==   S-  ss'   UU1   U:  d  GML  UU1	 GMR     U(       Gav  [        U 5      n2U2S:X  Gdd  U(       aF  UR7                  U2S9U:  nURW                  SS[Y        U
S5      -  [
        RZ                  " U5      S9nSn3URO                  WU2SS9n4[
        RP                  " U4S   [
        R,                  S9n#URS                  SS[
        RT                  -  U#S   S9n5[]        U4S   U4S   U W5       H  u  n6n'n7n8U5SU' n9U5U'S n5U6" U96 n0U8(       ah  URe                  URB                  W5        URg                  U[i        UW3   5      45         U3S-  n3UR	                  [c        U0UU7   /S95        SSS5        M  URa                  [c        U0UU7   /S95        M     U(       a  GM  U(       a  URe                  URB                  W5        U$ s  snf ! , (       d  f       GN= f! , (       d  f       M  = f)as  Generate random circuit of arbitrary size and form which strictly respects the interaction
graph passed as argument. Interaction Graph is a graph G=(V, E) where V are the qubits in the
circuit, and, E is the set of two-qubit gate interactions between two particular qubits in the
circuit.

This function will generate a random circuit by randomly selecting 1Q and 2Q gates from the set
of standard gates in :mod:`qiskit.circuit.library.standard_gates`. The user can attach a numerical
value as a metadata to the edge of the graph indicating the edge weight for that particular edge,
These edge weights would be normalized to the probabilities of the edges getting selected.
If all the edge weights are passed as `None`, then the probability of each qubit-pair of getting
selected is set to 1/N, where `N` is the number of edges in the `interaction_graph` passed in,
i.e each edge is drawn uniformly. If any weight of an edge is set as zero, that particular
edge will not be included in the output circuit.

Passing a list of tuples of control qubit, target qubit and associated probability is also
acceptable as a way to specify an interaction graph.

If numerical values are present as probabilities but some/any are None, or negative, when
`max_operands=2` this will raise a ValueError.

If `max_operands` is set to 1, then there are no 2Q operations, so no need to take care
of the edges, in such case the function will return a circuit from the `random_circuit` function,
which would be passed with the `max_operands` as 1.

If `max_operands` is set to 2, then in every while-iteration 2Q gates are chosen randomly, and
qubit-pairs which exist in the input interaction graph are also chosen randomly based on the
probability attached to the qubit-pair. Then in a for-iteration 2Q gates are applied to the
randomly chosen qubit-pairs with the aim to reach the count of 2Q on any qubit-pair to
`min_2q_gate_per_edge` criteria as soon as possible within a particular iteration. Now, if
some qubits are still idle after applying 2Q gates for that particular iteration, then randomly
chosen 1Q gates are applied to those idle qubits if `insert_1q_oper` is set to True.

Example:

.. plot::
   :alt: Pass in interaction graph and minimum 2Q gate per edge as a bare minimum.
   :include-source:

   from qiskit.circuit.random.utils import random_circuit_from_graph
   import rustworkx as rx
   pydi_graph = rx.PyDiGraph()
   pydi_graph.add_nodes_from(range(7))
   cp_map = [(0, 1, 0.18), (1, 2, 0.15), (2, 3, 0.15), (3, 4, 0.22), (4, 5, 0.13), (5, 6, 0.17)]
   pydi_graph.add_edges_from(cp_map)
   # cp_map can be passed in directly as interaction_graph
   qc = random_circuit_from_graph(pydi_graph, min_2q_gate_per_edge=2, seed=12345)
   qc.draw(output='mpl')

Args:
    interaction_graph (PyGraph | PyDiGraph | List[Tuple[int, int, float]]): Interaction Graph
    min_2q_gate_per_edge (int): Minimum number of times every qubit-pair must be used
        in the random circuit. (optional, default:1)
    max_operands (int): maximum qubit operands of each gate(should be 1 or 2)
        (optional, default:2)
    measure (bool): if True, measure all qubits at the end. (optional, default: False)
    conditional (bool): if True, insert middle measurements and conditionals.
        (optional, default: False)
    reset (bool): if True, insert middle resets. (optional, default: False)
    seed (int): sets random seed. (If `None`, a random seed is chosen) (optional)
    insert_1q_oper (bool): Insert 1Q operations to the circuit. (optional, default: True)
    prob_conditional (float): Probability less than 1.0, this is used to control the occurrence
        of conditionals in the circuit. (optional, default: 0.1)
    prob_reset (float): Probability less than 1.0, this is used to control the occurrence of
        reset in the circuit. (optional, default: 0.1)

Returns:
    QuantumCircuit: constructed circuit

Raises:
    CircuitError: When `max_operands` is not 1 or 2.
    CircuitError: When `max_operands` is set to 1, but no 1Q operations are allowed by setting
        `insert_1q_oper` to false.
    CircuitError: When the interaction graph has no edges, so only 1Q gates are possible in
        the circuit, but `insert_1q_oper` is set to False.
    CircuitError: When an invalid interaction graph object is passed.
    ValueError: Given `max_operands=2`, when any edge have probability `None` but not all, or any
        of the probabilities are negative.
>   r   r   z&`max_operands` should be either 1 or 2r   zR`max_operands` of 1 means only 1Q gates are allowed, but `insert_1q_oper` is Falser   Nz0Invalid interaction graph object has been passedzzThere are no edges in the `interaction_graph` so, there could be only 1Q gates, however `insert_1q_oper` is set to `False`)
num_qubitsdepthmax_operandsmeasureconditionalresetseedz Probabilities cannot be negativeg      ?gMbP?)rtolzSome of the probabilities of a qubit-pair getting selected is `None` It should either be all `None` or all positive numerical weights. classr   
num_paramsdtypecTr   copy)sizereplacep)r    r!   r   r    ?   	operationqubits)5r	   
isinstancelistlenappendnparrayr   	num_nodes	num_edges	edge_listedgesr   random_circuitall
ValueErrorsumiscloseanyonesgates_2q_dataobjectint64gates_1q_datar   r   add_registerrandomrandintiinfoint32maxdefault_rngr(   tuplezerosboolsetrangechoicecumsumuniformpiintegersmincount_nonzerozipr   _appendr   r   if_testint):interaction_graphmin_2q_gate_per_edger   r   r   r   r   insert_1q_operprob_conditional
prob_resetr   r0   r1   edges_probsctrltrgtprob_mask	probs_sumgates_2qgates_1qqccrrngr(   edge
edges_usedreset_2qcond_val_2qcond_val_1qcond_1qcond_2qqubit_idx_idleedge_choicesgate_choicescumsum_params
parametersclbit_2q_idxgatenum_gate_params
is_cond_2qis_rstcontrol_qubittarget_qubitis_rst_controlis_rst_targetrst_operparamscurrent_instr
_temp_edgenum_unused_qubitsclbit_1q_idxextra_1q_gatesparameters_1qgate_1q	qubit_idx
is_cond_1q	params_1qs:                                                             U/home/james-whalen/.local/lib/python3.13/site-packages/qiskit/circuit/random/utils.pyrandom_circuit_from_graphr   O   s   x 6!CDDq`
 	

 JIIK#T**)*		 1Dd\*t$ !
 !
 !2 	a
HHY'	hh{+	%y	1	1&002
%//1	HH.88:;	hh06689MNNQ#-#<<*LA~n9
 	

 A~* !&#
 	
 	Kq !%(e$	 	N	 ;  Dax !CDD  
  OO%	zz)U7%	1K	[		R
 	
 
	ggi(94xx <":\288<TUH
 88M@	
	#B+z3/
|yy  BHHRXX$6$:$:;
))


%CXXbiivD9F-67YT%+q.YJ7 HKK ((:T2((9D1 88IT2  U:./ zz	 " 
 zz(DzI		,|"<BHHM[[AIM"4E[F

 zz	1~z6CHjjc,&7j8;KKG,,q!s:r/B*BIYIYZaIb,cKL?B!&@
;D/4V +0+'M< 06- 7!JJ*&.$*=$9#: !JJ*&.$*<$8#9   01F#O$45J &MM

299b)ZZS\)B%C DE A%LII*&3$*=$96,;O#P FE 

&"/ &} 5vl7KL ,c$i7N (6JZ':&!+&j)-AA":.C@
F  #N 3$) !jj.?j@CSSG"%,,1J 33":J:J7:S #/ #K $%L "%H;LVZ![ "		.*Fbhh W #Aq255y}R?P QGJ"7+"<0"	HCG_i !..> ?I$1/2B$CM$+Y$7M!

299b1ZZS\1J-K(LM(A-LII 2.;,29,=+>!" NM 

.*7(.y(9':-Hk *d 


299b!IS 8t FEx NMs   	`'`#`(
`%	(
`7	num_operand_distributionc                 B   UcL  [         R                  R                  S[         R                  " [         R                  5      R
                  5      n[         R                  R                  U5      nU(       a  [        UR                  5       5      S:  d  [        UR                  5       5      S:  a  [        S5      eUR                  5        H$  u  pX:  d  M  U
S:w  d  M  [        SU	 SU  S	35      e   [        [        UR                  5       5      5      nU(       d  U(       a  US:  d  US:  a  [        S
5      eX:  a  UOU nUR                  [         R                  " U5      5      n[        U5       Vs0 s H
  oS-   X   _M     nn[        [        UR                  5       5      5      n[         R                   " [#        UR%                  5       5      S5      (       d  [        S5      eU S:X  a
  ['        5       $ [(        R*                  SS4[(        R,                  SS4[(        R.                  SS4[(        R0                  SS4/n[(        R2                  SS4[(        R4                  SS4/n[         R6                  " U(       a  [8        [:        SS4/-   O[8        S[<        4S[         R>                  4S[         R>                  4/S9n[         R6                  " [@        URB                  S9n[         R6                  " XRB                  S9n[         R6                  " XRB                  S9nUUX/n/ n/ nUR                  5        HI  u  nnUUS-
     nURE                  U5        URE                  U[G        U5      -  /[G        U5      -  5        MK     [         R6                  " UURB                  S9n['        U 5      nU(       d  U(       a  [I        U S5      nURK                  U5        [         R6                  " URL                  [<        SS9n[         RN                  " [G        U5      S-   [         R>                  S9nSn[        U5       GH  nURQ                  U[G        U5      US9n[         RR                  " US   [         R>                  S9n[         RT                  " UU SS9n USU  nU UU S-
     -
  n!US   n"U[         RV                  " U"[G        U5      S-   S9-  nU[G        U5      -  nU!S:  a  Sn#[        UR                  5       SS9 H  u  n	n$U!U	:  d  M  UU	   U-  U$:  d  M  [         R6                  " UU	S-
     URY                  S[G        UU	S-
     5      5         5      n%[         RZ                  " UU%45      nUU	==   S-  ss'   US-  nU!U	-  n!Sn#M     U#(       d  OU!S:  a  M  [         R\                  " [G        U5      S-   [         R>                  S9n&[         R\                  " [G        U5      S-   [         R>                  S9n'S=U&S'   U'S'   [         RR                  " US   U&SS S9  [         RR                  " US   U'SS S9  UR_                  SS[         R`                  -  U'S   S9n(URc                  U5        U(       Ga  US:w  Ga  UR                  [G        U5      S9S:  n)URY                  SS[        U S5      -  [         Rd                  " U)5      S9n*Sn+[g        US   U&SS U&SS U'SS U'SS U)5       H  u  n,n-n.n/n0n1U," U(U/U0 6 n2U1(       ag  URi                  URL                  W5        URk                  U[m        U*U+   5      45         U+S-  n+URo                  [q        U2UU-U. S 95        SSS5        M  URs                  [q        U2UU-U. S 95        M     GMT  [g        US   U&SS U&SS U'SS U'SS 5       H-  u  n,n-n.n/n0U," U(U/U0 6 n2URs                  [q        U2UU-U. S 95        M/     GM     U(       a  URi                  URL                  W5        U$ s  snf ! , (       d  f       GM1  = f)!a  Generate random circuit of arbitrary size and form.

This function will generate a random circuit by randomly selecting gates
from the set of standard gates in :mod:`qiskit.circuit.library.standard_gates`. For example:

.. plot::
   :alt: Circuit diagram output by the previous code.
   :include-source:

   from qiskit.circuit.random import random_circuit

   circ = random_circuit(2, 2, measure=True)
   circ.draw(output='mpl')

Args:
    num_qubits (int): number of quantum wires
    depth (int): layers of operations (i.e. critical path length)
    max_operands (int): maximum qubit operands of each gate (between 1 and 4)
    measure (bool): if True, measure all qubits at the end
    conditional (bool): if True, insert middle measurements and conditionals
    reset (bool): if True, insert middle resets
    seed (int): sets random seed (optional)
    num_operand_distribution (dict): a distribution of gates that specifies the ratio
        of 1-qubit, 2-qubit, 3-qubit, ..., n-qubit gates in the random circuit. Expect a
        deviation from the specified ratios that depends on the size of the requested
        random circuit. (optional)

Returns:
    QuantumCircuit: constructed circuit

Raises:
    CircuitError: when invalid options given
Nr   r   r   z9'num_operand_distribution' must have keys between 1 and 4g        z''num_operand_distribution' cannot have z-qubit gates for circuit with z qubitsz$max_operands must be between 1 and 4zAThe sum of all the values in 'num_operand_distribution' is not 1.r   r   r   r   r   r   Tr   )r    r"   right)side)	minlengthF)reverse)outr   r#   r$   皙?r%   r&   ):r-   r?   r@   rA   rB   rC   rD   rO   keysr	   itemsdictsorted	dirichletr9   rI   r7   r6   valuesr   r   CCXGate	CSwapGateCCZGateRCCXGateC3SXGateRC3XGater.   r=   r   r;   r<   r:   r   extendr+   r   r>   r(   rF   rJ   rK   searchsortedbincountrN   hstackemptyrL   rM   shufflerP   rQ   r   rS   rT   r,   r   rR   )3r   r   r   r   r   r   r   r   rd   keyr]   	rand_distigates_3qgates_4qra   r`   all_gate_listsgates_to_considerdistributionn_qubitsratio	gate_listgatesrb   rc   r(   countertotal_gateslayer_number
gate_specscumulative_qubits	max_indexslackgate_qubitsgate_added_flagdistgate_to_add	q_indices	p_indicesrp   is_conditionalcondition_valuesc_ptrrr   q_startq_endp_startp_endis_condr'   s3                                                      r   r3   r3     s   V |yy  BHHRXX$6$:$:;
))


%C',,./!3s;S;X;X;Z7[^_7_Z[[1779ICDCK"=cU C))3G=  : $(/G/M/M/O(P#Q #!|a/EFF'1'@|jMMGGL!
	 BG|AT#UATAE9<$7AT #U#'/G/M/M/O(P#Q  ::c299;<a@@^__Q 
		A&		!	!1a(			A&		 	 !Q'	H 
	 	 !Q'		 	 !Q'H
 xx+0%A'm <":\288<TUH
 xxX^^<Hxx7Hxx7H(=N
 L399;%"8a<0	  +US^34s9~EF <
 HH&hnn=E	
	#B+z3/
XXbiivD9F hhs>*Q.bhh?GK e ZZCK<ZH
IIj&>bhhO
 OO$5zP	
+
.y1}== !.2;;{c.6IA6MNNs:& ai#O#$<$B$B$DdS	TC<GCL;$>$E"$((&sQw/QNSVYZSZD[@\0]^#K "$J+D!EJCLA%L1$KSLE&*O T # ai& HHS_q0A	HHS_q0A	&''	!y|
		*\*	!">
		*\*	!">[[AIIbM[B
F
 <1, ZZS_Z=CN"||1J++"2B2B>2R  ,   EAD7##2!"#2!"B=gugug !*WU";<	JJryy"-R-=e-D)E$FG
		.6RYZ_K`a HG JJ*YvgV[G\]'B. 9<7#Ys^Yqr]IcrNT]^_^`Ta94gugu !*WU";<	

-	&QXY^J_`a	9y %B 


299b!I $VZ HGs   5`	"`
`c                     [        [        [        R                  " 5       5      1 Sk-
  5      n[        [        R                  " 5       5      nUS:X  a  U S:X  a  UnOXE-   n0 S[
        R                  " 5       S4_S[
        R                  " 5       S4_S[
        R                  " 5       S4_S[
        R                  " 5       S4_S[
        R                  " 5       S4_S	[
        R                  " 5       S4_S
[
        R                  " 5       S4_S[
        R                  " 5       S4_S[
        R                  " 5       S4_S[
        R                  " 5       S4_S[
        R                   " 5       S4_S[
        R"                  " 5       S4_S[
        R$                  " 5       S4_S[
        R&                  " 5       S4_S[
        R(                  " 5       S4_S[
        R*                  " 5       S4_n[-        U[.        R0                  R2                  5      (       a  UnO[.        R0                  R5                  U5      nUR7                  X!5      n[9        U 5      n	U HA  n
Xj   u  pUR7                  [;        U 5      USS9R=                  5       nU	R?                  XSS9  MC     U	$ )am  Generate a pseudo-random Clifford circuit.

This function will generate a Clifford circuit by randomly selecting the chosen amount of Clifford
gates from the set of standard gates in :mod:`qiskit.circuit.library.standard_gates`. For example:

.. plot::
   :alt: Circuit diagram output by the previous code.
   :include-source:

   from qiskit.circuit.random import random_clifford_circuit

   circ = random_clifford_circuit(num_qubits=2, num_gates=6)
   circ.draw(output='mpl')

Args:
    num_qubits (int): number of quantum wires.
    num_gates (int): number of gates in the circuit.
    gates (list[str]): optional list of Clifford gate names to randomly sample from.
        If ``"all"`` (default), use all Clifford gates in the standard library.
    seed (int | np.random.Generator): sets random seed/generator (optional).

Returns:
    QuantumCircuit: constructed circuit
>   vwididensinvr4   r   r   xyzhssdgsxsxdgcxr   cyczswapiswapecrdcxF)r!   )r   ) r*   rH   r
   r   r   r   IGateXGateYGateZGateHGateSGateSdgGateSXGateSXdgGateCXGateCYGateCZGateSwapGate	iSwapGateECRGateDCXGater)   r-   r?   	GeneratorrD   rJ   r   rI   tolistr,   )r   	num_gatesr   r   ra   r`   instructionsrd   samplescircnamerr   nqargsqargss                 r   random_clifford_circuitr     s   4 C	(),LLMHINN$%H~?E'En""$a(n""$a( 	n""$a( 	n""$a(	
 	n""$a( 	n""$a( 	&&(!, 	~$$&* 	((*A. 	~$$&* 	~$$&* 	~$$&* 	((*A. 	.**,a0 	&&(!,  	&&(!,!L& $		++,,ii##D)jj*G*%D#)

5,fe
DKKMDe, 
 K    )	r   r   FFFNTr   r   )r   FFFNN)r4   N)C__doc__numpyr-   	rustworkxr   qiskit.circuitr   r   r   r   qiskit.circuit.libraryr   qiskit.circuit.exceptionsr	   :qiskit.quantum_info.operators.symplectic.clifford_circuitsr
   r   r   r   r   RZGateRGater   	PhaseGateRXGateRYGater   r   r   TGateTdgGateUGateU1GateU2GateU3Gater   r   r=   r   r   CHGate
CPhaseGateCRXGateCRYGateCRZGateCSXGateCUGateCU1GateCU3Gater   r   RXXGateRYYGateRZZGateRZXGateXXMinusYYGateXXPlusYYGater   CSGateCSdgGater   r   r:   r   r   r3   r    r   r   <module>r     sJ   8   
 ! 1 2 [ 1a Aq!1a Aq!1a 1a q!$Aq!Aq!1a Q"a#1a Q"1a Aq!Aq!Aq!1a 1a )0 Aq!Q"Aq!1%Q"Q"Q"Q"Aq!Q"Q"Aq!Aq!Q"Q"Q"Q"!!1a(  !Q'Q"Aq!a#a#q!$1< 
	z@ 
	%)` #`FDr   