
    z	i0                        S r SSKJr  SSK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  S
SKJr   " S S\5      r " S S\5      rg)a}  
=======================================================================================================
Solovay-Kitaev Synthesis Plugin (in :mod:`qiskit.transpiler.passes.synthesis.solovay_kitaev_synthesis`)
=======================================================================================================

.. autosummary::
   :toctree: ../stubs/

   SolovayKitaevSynthesis
    )annotationsN)circuit_to_dag)Gate)
DAGCircuit)SolovayKitaevDecomposition)TransformationPass)trivial_recurse   )UnitarySynthesisPluginc                  h   ^  \ rS rSrSr  S	SSS.         S
U 4S jjjjr\SS j5       rSrU =r	$ )SolovayKitaev&   u&  Approximately decompose 1q gates to a discrete basis using the Solovay-Kitaev algorithm.

The Solovay-Kitaev theorem [1] states that any single qubit gate can be approximated to
arbitrary precision by a set of fixed single-qubit gates, if the set generates a dense
subset in :math:`SU(2)`. This is an important result, since it means that any single-qubit
gate can be expressed in terms of a discrete, universal gate set that we know how to implement
fault-tolerantly. Therefore, the Solovay-Kitaev algorithm allows us to take any
non-fault tolerant circuit and rephrase it in a fault-tolerant manner.

This implementation of the Solovay-Kitaev algorithm is based on [2].

For example, the following circuit

.. code-block:: text

         ┌─────────┐
    q_0: ┤ RX(0.8) ├
         └─────────┘

can be decomposed into

.. code-block:: text

    global phase: 7π/8
         ┌───┐┌───┐┌───┐
    q_0: ┤ H ├┤ T ├┤ H ├
         └───┘└───┘└───┘

with an L2-error of approximately 0.01.

Examples:

    Per default, the basis gate set is ``["t", "tdg", "h"]``:

    .. plot::
       :include-source:
       :nofigs:

        import numpy as np
        from qiskit.circuit import QuantumCircuit
        from qiskit.transpiler.passes.synthesis import SolovayKitaev
        from qiskit.quantum_info import Operator

        circuit = QuantumCircuit(1)
        circuit.rx(0.8, 0)

        print("Original circuit:")
        print(circuit.draw())

        skd = SolovayKitaev(recursion_degree=2)

        discretized = skd(circuit)

        print("Discretized circuit:")
        print(discretized.draw())

        print("Error:", np.linalg.norm(Operator(circuit).data - Operator(discretized).data))

    .. code-block:: text

        Original circuit:
           ┌─────────┐
        q: ┤ Rx(0.8) ├
           └─────────┘
        Discretized circuit:
        global phase: 7π/8
           ┌───┐┌───┐┌───┐
        q: ┤ H ├┤ T ├┤ H ├
           └───┘└───┘└───┘
        Error: 2.828408279166474

    For individual basis gate sets, the ``generate_basic_approximations`` function can be used:

    .. plot::
       :include-source:
       :nofigs:

        from qiskit.synthesis import generate_basic_approximations
        from qiskit.transpiler.passes import SolovayKitaev

        basis = ["s", "sdg", "t", "tdg", "z", "h"]
        approx = generate_basic_approximations(basis, depth=3)

        skd = SolovayKitaev(recursion_degree=2, basic_approximations=approx)

References:

    [1]: Kitaev, A Yu (1997). Quantum computations: algorithms and error correction.
         Russian Mathematical Surveys. 52 (6): 1191–1249.
         `Online <https://iopscience.iop.org/article/10.1070/RM1997v052n06ABEH002155>`_.

    [2]: Dawson, Christopher M.; Nielsen, Michael A. (2005) The Solovay-Kitaev Algorithm.
         `arXiv:quant-ph/0505030 <https://arxiv.org/abs/quant-ph/0505030>`_.

N   basis_gatesdepthc               L   > [         TU ]  5         Xl        [        X#US9U l        g)a  
Args:
    recursion_degree: The recursion depth for the Solovay-Kitaev algorithm.
        A larger recursion depth increases the accuracy and length of the
        decomposition.
    basic_approximations: The basic approximations for the finding the best discrete
        decomposition at the root of the recursion. If a string, it specifies the
        file to load the approximations from. If a dictionary, it contains
        ``{label: SO(3)-matrix}`` pairs. If ``None``, a default based on the :math:`H`,
        :math:`T` and :math:`T^\dagger` gates up to depth 16 is generated.
        Note that if ``basic_approximations`` is passed, ``basis_gates`` and
        ``depth`` cannot be set.
    basis_gates: The basis gates used to build the net of basic approximations.
        Defaults to ``["h", "t", "tdg"]``. This argument cannot be set if
        ``basic_approximations`` is provided.
    depth: The maximal gate depth used in basic approximations. This argument cannot be
        set if ``basic_approximations`` is provided.
r   N)super__init__recursion_degreer   _sk)selfr   basic_approximationsr   r   	__class__s        u/home/james-whalen/.local/lib/python3.13/site-packages/qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.pyr   SolovayKitaev.__init__   s'    4 	 0- 
    c                   UR                  5        H  nUR                  R                  S:w  d0  UR                  5       (       d  [	        UR                  S5      (       d  MO  [        UR                  [        5      (       + nU R                  R                  UR                  U R                  SUS9nUR                  X$5        M     U$ )zRun the ``SolovayKitaev`` pass on `dag`.

Args:
    dag: The input dag.

Returns:
    Output dag with 1q gates synthesized in the discrete target basis.

Raises:
    TranspilerError: if a gates does not have to_matrix
r
   	to_matrixT)
return_dagcheck_input)op_nodesop
num_qubitsis_parameterizedhasattr
isinstancer   r   runr   substitute_node_with_dag)r   dagnoder!   approximations        r   r(   SolovayKitaev.run   s     LLND ##q(((**55 )$77K !HHLL..4[ ) M
 ((=' #* 
r   )r   r   )   N)
r   intr   z"str | dict[str, np.ndarray] | Noner   zlist[str | Gate] | Noner   r/   returnNone)r*   r   r0   r   )
__name__
__module____qualname____firstlineno____doc__r   r	   r(   __static_attributes____classcell__)r   s   @r   r   r   &   so    ^D !"CG

 04

 A

 -
 
 

 
@ ! !r   r   c                      \ rS rSrSrSrSrSr\S 5       r	\S 5       r
\S 5       r\S 5       r\S 5       r\S	 5       r\S
 5       r\S 5       r\S 5       rS rSrg)SolovayKitaevSynthesis   a  A Solovay-Kitaev Qiskit unitary synthesis plugin.

This plugin is invoked by :func:`~.compiler.transpile` when the ``unitary_synthesis_method``
parameter is set to ``"sk"``.

This plugin supports customization and additional parameters can be passed to the plugin
by passing a dictionary as the ``unitary_synthesis_plugin_config`` parameter of
the :func:`~qiskit.compiler.transpile` function.

Supported parameters in the dictionary:

basic_approximations (str | dict):
    The basic approximations for the finding the best discrete decomposition at the root of the
    recursion. If a string, it specifies the ``.npy`` file to load the approximations from.
    If a dictionary, it contains ``{label: SO(3)-matrix}`` pairs. If None, a default based on
    the specified ``basis_gates`` and ``depth`` is generated.

basis_gates (list):
    A list of strings specifying the discrete basis gates to decompose to. If None,
    it defaults to ``["h", "t", "tdg"]``. If ``basic_approximations`` is not None,
    ``basis_set`` is required to correspond to the basis set that was used to
    generate it.

depth (int):
    The gate-depth of the basic approximations. All possible, unique combinations of the
    basis gates up to length ``depth`` are considered. If None, defaults to 12.
    If ``basic_approximations`` is not None, ``depth`` is required to correspond to the
    depth that was used to generate it.

recursion_degree (int):
    The number of times the decomposition is recursively improved. If None, defaults to 5.
Nc                    g)z,Maximum number of supported qubits is ``1``.r
    r   s    r   
max_qubits!SolovayKitaevSynthesis.max_qubits        r   c                    g)z,Minimum number of supported qubits is ``1``.r
   r=   r>   s    r   
min_qubits!SolovayKitaevSynthesis.min_qubits   rA   r   c                    g)z`The plugin does not support natural direction, it does not assume
bidirectional two qubit gates.Tr=   r>   s    r   supports_natural_direction1SolovayKitaevSynthesis.supports_natural_direction       r   c                    g)z3The plugin does not support optimization of pulses.Fr=   r>   s    r   supports_pulse_optimize.SolovayKitaevSynthesis.supports_pulse_optimize
       r   c                    g)z)The plugin does not support gate lengths.Fr=   r>   s    r   supports_gate_lengths,SolovayKitaevSynthesis.supports_gate_lengths  rL   r   c                    g)z(The plugin does not support gate errors.Fr=   r>   s    r   supports_gate_errors+SolovayKitaevSynthesis.supports_gate_errors  rL   r   c                    g)z0The plugin does not support bases for synthesis.Nr=   r>   s    r   supported_bases&SolovayKitaevSynthesis.supported_bases  s     r   c                    g)ziThe plugin does not support basis gates. By default it synthesis to the
``["h", "t", "tdg"]`` gate basis.Tr=   r>   s    r   supports_basis_gates+SolovayKitaevSynthesis.supports_basis_gates  rH   r   c                    g)z*The plugin does not support coupling maps.Fr=   r>   s    r   supports_coupling_map,SolovayKitaevSynthesis.supports_coupling_map$  rL   r   c                   UR                  S5      =(       d    0 nUR                  SS5      nUR                  SS5      nUR                  SS5      nUR                  SS5      n[        R                  b(  U[        R                  :w  d  U[        R                  :w  a)  U[        l        U[        l        [        XdUS	9[        l        [        R                  R                  X5      n[        U5      $ )
zERun the SolovayKitaevSynthesis synthesis plugin on the given unitary.configr   Nr   r   r   r   r.   r   )getr:   r   _basis_gates_depthr   r(   r   )	r   unitaryoptionsr]   r   r   r   r   approximate_circuits	            r   r(   SolovayKitaevSynthesis.run)  s     X&,"kk-6

7B'%zz*@$G!::&8!< #&&.2???/6662="/,1"))C$U*"& 588<<WW122r   r=   )r2   r3   r4   r5   r6   r   r_   r`   propertyr?   rC   rF   rJ   rN   rQ   rT   rW   rZ   r(   r7   r=   r   r   r:   r:      s    R CLF     
          
  3r   r:   )r6   
__future__r   numpynpqiskit.convertersr   qiskit.circuit.gater   qiskit.dagcircuitr   .qiskit.synthesis.discrete_basis.solovay_kitaevr   qiskit.transpiler.basepassesr   +qiskit.transpiler.passes.utils.control_flowr	   pluginr   r   r:   r=   r   r   <module>rp      sF   	 #  , $ ( U ; G *c& cLr33 r3r   