
    biL                     $   d Z ddlZddlmZ ddlmZ ddlZddlm	Z	 ddl
mZ ddlmZ ddlmZ d	 Zd
 Zd#defdZd#defdZd#defdZdefdZdefdZdefdZdefdZdZd$dedefdZd Zd Zd Zd Z d Z!d Z"d Z#d Z$d Z%d  Z&d! Z'd" Z(y)%a,  
Copyright 2013 Steven Diamond

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
    N)defaultdictFraction)reshape)vstack)SOC)Variablec                     | j                   }t        t        ||z   |fd      t        t        ||z
  d|fd      t        d| z  d|fd      g      d      S )NF)order      r   )tXaxis)sizer   r   r   )r   xylengths       V/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/cvxpy/utilities/power_tools.pygmr      sc    VVF1vis31Q3F371Q3F37       c           	      6    t        |      sJ t        |      }t        |      }t         fd      } ||<   t	        |      t	        |      z
  }|dkD  r	| g|z  z  }t	        |      t	        |      k(  sJ t        t        ||            D ]0  \  }\  }}|dkD  sdgt	        |      z  }	d|	|<   ||t        |	      <   2 g }
|j                         D ]*  \  }}d|vs|
t        ||   ||d      ||d            gz  }
, t	        |      dk(  r|d   }|
 |k(  gz  }
|
S )a   Form the internal CXVPY constraints to form the weighted geometric mean t <= x^p.

    t <= x[0]^p[0] * x[1]^p[1] * ... * x[n]^p[n]

    where x and t can either be scalar or matrix variables.

    Parameters
    ----------

    t : cvx.Variable
        The epigraph variable

    x_list : list of cvx.Variable objects
        The vector of input variables. Must be the same length as ``p``.

    p : list or tuple of ``int`` and ``Fraction`` objects
        The powers vector. powers must be nonnegative and sum to *exactly* 1.
        Must be the same length as ``x``.

    Returns
    -------
    constr : list
        list of constraints involving elements of x (and possibly t) to form the geometric mean.

    c                  .    t         j                        S N)r	   shaper   s   r   <lambda>zgm_constrs.<locals>.<lambda>E   s    HQWW- r   r   r   )
	is_weightdyad_completion	decomposer   len	enumerateziptupleitemsr   )r   x_listpwtreedlong_wivtmpconstraintselemchildrenr   s   `             r   
gm_constrsr3   '   sE   4 Q<<AQ<D-.AAaDVc&k!Fz1#f*v;#a&   s1f~. 	6Aqq5#c!f*CCFAeCjM	 K**, IhD=Bqw(1+(1+GHHKI
 6{a1IQxr   	max_denomc                     | dkD  sJ t        dt        |       z        j                  |      } d| z  t        d| z        k(  rt        d| z        | d| z
  ffS d| z  | d| z
  ffS )zl Return (t,1,x) power tuple

        x <= t^(1/p) 1^(1-1/p)

        user wants the epigraph variable t
    r   )r   limit_denominatorintr(   r4   s     r   pow_highr9   b   sp     q5L58A;11)<Asc!A#h1Q3x!QqS!!Q3AaC=r   c                 h    d| cxk  rdk  sJ  J t        |       j                  |      } | | d| z
  ffS )zf Return (x,1,t) power tuple

        t <= x^p 1^(1-p)

        user wants the epigraph variable t
    r   r   r   r6   r8   s     r   pow_midr<   p   s?     q91999%%i0Aq!A#h;r   c                     | dk  sJ t        |       } t        | | dz
  z        j                  |      } | | dz
  z  | d| z
  ffS )zs Return (x,t,1) power tuple

        1 <= x^(p/(p-1)) t^(-1/(p-1))

        user wants the epigraph variable t
    r   r   r;   r8   s     r   pow_negr>   |   sP     q5L5AAaC++I6Aac7Q!Hr   returnc                 Z    t        | t        j                        xr | dkD  xr	 | | dz
  z   S )a   Test if num is a positive integer power of 2.

    .. note::
        Fails if num is a np.integer type like np.int32, np.int64, etc.
        This seems to be a Python 3 issue.
        Make sure to convert all integers to the native python ``int`` type.

    Examples
    --------
    >>> is_power2(4)
    True
    >>> is_power2(2**10)
    True
    >>> is_power2(1)
    True
    >>> is_power2(1.0)
    False
    >>> is_power2(0)
    False
    >>> is_power2(-4)
    False
    r   r   )
isinstancenumbersIntegral)nums    r   	is_power2rE      s0    . c7++,RqR#q/=RRr   c                     t        | t        j                        r| dk\  ryt        | t              r| dk\  rt	        | j
                        ryy)a7   Test if frac is a nonnegative dyadic fraction or integer.

    Examples
    --------
    >>> is_dyad(Fraction(1,4))
    True
    >>> is_dyad(Fraction(1,3))
    False
    >>> is_dyad(0)
    True
    >>> is_dyad(1)
    True
    >>> is_dyad(-Fraction(1,4))
    False
    >>> is_dyad(Fraction(1,6))
    False

    r   TF)rA   rB   rC   r   rE   denominator)fracs    r   is_dyadrI      s@    & $(()dai	D(	#	i@P@P6Qr   c                 @    t        |       xr t        d | D              S )ax   Test if a vector is a valid dyadic weight vector.

        w must be nonnegative, sum to 1, and have integer or dyadic fractional elements.

        Examples
        --------
        >>> is_dyad_weight((Fraction(1,2), Fraction(1,2)))
        True
        >>> is_dyad_weight((Fraction(1,3), Fraction(2,3)))
        False
        >>> is_dyad_weight((0, 1, 0))
        True
    c              3   2   K   | ]  }t        |        y wr   )rI   .0fs     r   	<genexpr>z!is_dyad_weight.<locals>.<genexpr>   s     6q
6   )r   all)r)   s    r   is_dyad_weightrR      s     Q<6C6A666r   c                     t        | t        j                        r| j                         } t	        d | D              }|xr t        |       dk(  S )a   Test if w is a valid weight vector.
        w must have nonnegative integer or fractional elements, and sum to 1.

    Examples
    --------
    >>> is_weight((Fraction(1,3), Fraction(2,3)))
    True
    >>> is_weight((Fraction(2,3), Fraction(2,3)))
    False
    >>> is_weight([.1, .9])
    False
    >>> import numpy as np
    >>> w = np.array([.1, .9])
    >>> is_weight(w)
    False
    >>> w = np.array([0, 0, 1])
    >>> is_weight(w)
    True
    >>> w = (0,1,0)
    >>> is_weight(w)
    True

    c              3   j   K   | ]+  }|d k\  xr  t        |t        j                  t        f       - ywr   NrA   rB   rC   r   rM   r.   s     r   rO   zis_weight.<locals>.<genexpr>   s?      NFG 1f B W%5%5x$@AB Ns   13r   )rA   npndarraytolistrQ   sum)r)   valid_elemss     r   r   r      sJ    0 !RZZ HHJ NKLN NK&3q6Q;&r   z
    Can't reliably represent the input weight vector.
    Try increasing `max_denom` or checking the denominators
    of your input fractions.
    
force_dyadc                    t        d | D              rt        d      t        t        j                        rdkD  st        d      t        | t
        j                        r| j                         } t              t        |       |du rt        |       }n{t        d | D              r:t        fd| D              }t        d |D              }|kD  r>t        t              t        fd	| D              }t        |      d
k7  rt        |       }t        |      }t        d |D              kD  rt        t              ||fS )a   Return a valid fractional weight tuple (and its dyadic completion)
        to represent the weights given by ``a``.

        When the input tuple contains only integers and fractions,
        ``fracify`` will try to represent the weights exactly.

    Parameters
    ----------
    a : Sequence
        Sequence of numbers (ints, floats, or Fractions) to be represented
        with fractional weights.

    max_denom : int
        The maximum denominator allowed for the fractional representation.
        When the fractional representation is not exact, increasing
        ``max_denom`` will typically give a better approximation.

        Note that ``max_denom`` is actually replaced with the largest power
        of 2 >= ``max_denom``.

    force_dyad : bool
        If ``True``, we force w to be a dyadic representation so that ``w == w_dyad``.
        This means that ``w_dyad`` does not need an extra dummy variable.
        In some cases, this may reduce the number of second-order cones needed to
        represent ``w``.

    Returns
    -------
    w : tuple
        Approximation of ``a/sum(a)`` as a tuple of fractions.

    w_dyad : tuple
        The dyadic completion of ``w``.

        That is, if w has fractions with denominators that are not a power of 2,
        and ``len(w) == n`` then w_dyad has length n+1, dyadic fractions for elements,
        and ``w_dyad[:-1]/w_dyad[n] == w``.
        # ^ That isn't always possible, is it?

        Alternatively, the ratios between the
        first n elements of ``w_dyad`` are equal to the corresponding ratios between
        the n elements of ``w``.

        The dyadic completion of w is needed to represent the weighted geometric
        mean with weights ``w`` as a collection of second-order cones.

        The appended element of ``w_dyad`` is typically a dummy variable.

    Examples
    --------
    >>> w, w_dyad = fracify([1, 2, 3])
    >>> w
    (Fraction(1, 6), Fraction(1, 3), Fraction(1, 2))
    >>> w_dyad
    (Fraction(1, 8), Fraction(1, 4), Fraction(3, 8), Fraction(1, 4))

    >>> w, w_dyad = fracify((1, 1, 1, 1, 1))
    >>> w
    (Fraction(1, 5), Fraction(1, 5), Fraction(1, 5), Fraction(1, 5), Fraction(1, 5))
    >>> w_dyad
    (Fraction(1, 8), Fraction(1, 8), Fraction(1, 8), Fraction(1, 8), Fraction(1, 8), Fraction(3, 8))

    >>> w, w_dyad = fracify([.23, .56, .87])
    >>> w
    (Fraction(23, 166), Fraction(28, 83), Fraction(87, 166))
    >>> w_dyad
    (Fraction(23, 256), Fraction(7, 32), Fraction(87, 256), Fraction(45, 128))

    >>> w, w_dyad = fracify([3, Fraction(1, 2), Fraction(3, 5)])
    >>> w
    (Fraction(30, 41), Fraction(5, 41), Fraction(6, 41))
    >>> w_dyad
    (Fraction(15, 32), Fraction(5, 64), Fraction(3, 32), Fraction(23, 64))

    Can also mix integer, Fraction, and floating point types.

    >>> w, w_dyad = fracify([3.4, 8, Fraction(3, 2)])
    >>> w
    (Fraction(34, 129), Fraction(80, 129), Fraction(5, 43))
    >>> w_dyad
    (Fraction(17, 128), Fraction(5, 16), Fraction(15, 256), Fraction(127, 256))

    Forcing w to be dyadic makes it its own dyadic completion.

    >>> w, w_dyad = fracify([3.4, 8, Fraction(3, 2)], force_dyad=True)
    >>> w
    (Fraction(135, 512), Fraction(635, 1024), Fraction(119, 1024))
    >>> w_dyad
    (Fraction(135, 512), Fraction(635, 1024), Fraction(119, 1024))

    A standard basis unit vector should yield itself.

    >>> w, w_dyad = fracify((0, 0.0, 1.0))
    >>> w
    (Fraction(0, 1), Fraction(0, 1), Fraction(1, 1))
    >>> w_dyad
    (Fraction(0, 1), Fraction(0, 1), Fraction(1, 1))

    A dyadic weight vector should also yield itself.

    >>> a = (Fraction(1,2), Fraction(1,8), Fraction(3,8))
    >>> w, w_dyad = fracify(a)
    >>> a == w == w_dyad
    True

    Be careful when converting floating points to fractions.

    >>> a = (Fraction(.9), Fraction(.1))
    >>> w, w_dyad = fracify(a)
    Traceback (most recent call last):
    ...
    ValueError: Can't reliably represent the input weight vector.
    Try increasing `max_denom` or checking the denominators of your input fractions.

    The error here is because ``Fraction(.9)`` and ``Fraction(.1)``
    evaluate to ``(Fraction(8106479329266893, 9007199254740992)`` and
    ``Fraction(3602879701896397, 36028797018963968))``.

    c              3   &   K   | ]	  }|d k    ywrU    rW   s     r   rO   zfracify.<locals>.<genexpr>n  s     
Q1q5
   z!Input powers must be nonnegative.r   z%Input denominator must be an integer.Tc              3   \   K   | ]$  }t        |t        j                  t        f       & y wr   rV   rW   s     r   rO   zfracify.<locals>.<genexpr>|  s"     DQZG,,h78Ds   *,c              3   6   K   | ]  }t        |        y wr   r   )rM   r.   totals     r   rO   zfracify.<locals>.<genexpr>}  s     5ax5)5   c              3   4   K   | ]  }|j                     y wr   rG   rW   s     r   rO   zfracify.<locals>.<genexpr>~  s     .!.   c              3   j   K   | ]*  }t        t        |      z        j                         , y wr   )r   floatr6   )rM   r.   r4   rd   s     r   rO   zfracify.<locals>.<genexpr>  s*     XQRxa/AA)LXs   03r   c              3   4   K   | ]  }|j                     y wr   rg   rW   s     r   rO   zfracify.<locals>.<genexpr>  s     
)Q1==
)rh   )any
ValueErrorrA   rB   rC   rX   rY   rZ   	next_pow2r[   	make_fracrQ   r%   max__EXCEED_DENOMINATOR_LIMIT__r    )ar4   r]   w_fracr+   w_dyadrd   s    `    @r   fracifyru      s!   p 
!
<==y'"2"23	A@AA!RZZ HHJ)$IFET1i(	D!D	D5155.v..y=9:: XVWXXv;!q),FV$F

)&
))I55666>r   c                 d   t        j                  | t              t        |       z  } | z  j	                  t
              }|t              z  | z
  }t        j                  |      dt        |      z
   }||xx   dz  cc<   t              |j                         }t        fd|D              S )ax   Approximate ``a/sum(a)`` with tuple of fractions with denominator *exactly* ``denom``.

    >>> a = [.123, .345, .532]
    >>> make_frac(a,10)
    (Fraction(1, 10), Fraction(2, 5), Fraction(1, 2))
    >>> make_frac(a,100)
    (Fraction(3, 25), Fraction(7, 20), Fraction(53, 100))
    >>> make_frac(a,1000)
    (Fraction(123, 1000), Fraction(69, 200), Fraction(133, 250))
    dtypeNr   c              3   6   K   | ]  }t        |        y wr   r   )rM   r.   denoms     r   rO   zmake_frac.<locals>.<genexpr>  s     /!U#/re   )	rX   arrayrj   r[   astyper7   argsortrZ   r%   )rr   rz   berrindss    `   r   ro   ro     s     	% Q'A	3A
E%L.1
C::c?,USV^-DdGqLGJE	
A/Q///r   c                 @   t        d | D              } | D cg c]$  }t        |j                        r|j                  & }}t        |      dkD  rGt	        |      t              t        fd| D              t        z
        fz   }t        |      S | S c c}w )a   Return the dyadic completion of ``w``.

        Return ``w`` if ``w`` is already dyadic.

        We assume the input is a tuple of nonnegative Fractions or integers which sum to 1.

    Examples
    --------
    >>> w = (Fraction(1,3), Fraction(1,3), Fraction(1, 3))
    >>> dyad_completion(w)
    (Fraction(1, 4), Fraction(1, 4), Fraction(1, 4), Fraction(1, 4))

    >>> w = (Fraction(1,3), Fraction(1,5), Fraction(7, 15))
    >>> dyad_completion(w)
    (Fraction(5, 16), Fraction(3, 16), Fraction(7, 16), Fraction(1, 16))

    >>> w = (1, 0, 0.0, Fraction(0,1))
    >>> dyad_completion(w)
    (Fraction(1, 1), Fraction(0, 1), Fraction(0, 1), Fraction(0, 1))
    c              3   2   K   | ]  }t        |        y wr   r   rW   s     r   rO   z"dyad_completion.<locals>.<genexpr>  s     %ahqk%rP   r   c              3   <   K   | ]  }t        |z          y wr   r   )rM   r.   r+   r(   s     r   rO   z"dyad_completion.<locals>.<genexpr>  s     21hqsA&2s   )r%   rE   rG   r"   rp   rn   r   r    )r)   r.   non_dyad_densw_augr+   r(   s       @@r   r    r      s    * 	%1%%A,-NqYq}}5MQ]]NMN
=AaL222hqsA6F5HHu%% Os
   BBc           	         t        d | D              sJ t        |      sJ t        |       t        |      k(  sJ t        j                  | t
              t        |       z  }t        t        d t        ||      D                    S )ac   Return the :math:`\ell_\infty` norm error from approximating the vector a_orig/sum(a_orig)
        with the weight vector w_approx.

        That is, return

        .. math:: \|a/\mathbf{1}^T a - w_{\mbox{approx}} \|_\infty


        >>> e = approx_error([1, 1, 1], [Fraction(1,3), Fraction(1,3), Fraction(1,3)])
        >>> e <= 1e-10
        True
    c              3   &   K   | ]	  }|d k\    ywrU   r`   rW   s     r   rO   zapprox_error.<locals>.<genexpr>  s     &!qAv&ra   rw   c              3   >   K   | ]  \  }}t        ||z
          y wr   )abs)rM   v1v2s      r   rO   zapprox_error.<locals>.<genexpr>  s     DFBSBZDs   )	rQ   r   r"   rX   r{   rj   r[   rp   r$   )a_origw_approxw_origs      r   approx_errorr     sr     &v&&&&Xv;#h-'''XXfE*3v;6FDc&(.CDDEEr   c                 ^    | dk  rydt        |       j                         z  }|dz	  | k(  r| S |S )z Return first power of 2 >= n.

    >>> next_pow2(3)
    4
    >>> next_pow2(8)
    8
    >>> next_pow2(0)
    1
    >>> next_pow2(1)
    1
    r   r   )r7   
bit_length)nn2s     r   rn   rn     s:     	Av	
c!f!	!B	Qw!|	r   c                     t        |       rt              sy| k(  ryt              t        |       dz   k(  r| t        fddd D              k(  S y)a  Check that w_dyad is a valid dyadic completion of w.

    Parameters
    ----------
    w : Sequence
        Tuple of nonnegative fractional or integer weights that sum to 1.
    w_dyad : Sequence
        Proposed dyadic completion of w.

    Returns
    -------
    bool
        True if w_dyad is a valid dyadic completion of w.


    Examples
    --------
    >>> w = (Fraction(1,3), Fraction(1,3), Fraction(1,3))
    >>> w_dyad =(Fraction(1,4), Fraction(1,4), Fraction(1,4), Fraction(1,4))
    >>> check_dyad(w, w_dyad)
    True

    If the weight vector is already dyadic, it is its own completion.

    >>> w = (Fraction(1,4), 0, Fraction(3,4))
    >>> check_dyad(w, w)
    True

    Integer input should also be accepted

    >>> w = (1, 0, 0)
    >>> check_dyad(w, w)
    True

    w is not a valid weight vector here because it doesn't sum to 1

    >>> w = (Fraction(2,3), 1)
    >>> check_dyad(w, w)
    False

    w_dyad isn't the correct dyadic completion.

    >>> w = (Fraction(2,5), Fraction(3,5))
    >>> w_dyad = (Fraction(3,8), Fraction(4,8), Fraction(1,8))
    >>> check_dyad(w, w_dyad)
    False

    The correct dyadic completion.

    >>> w = (Fraction(2,5), Fraction(3,5))
    >>> w_dyad = (Fraction(2,8), Fraction(3,8), Fraction(3,8))
    >>> check_dyad(w, w_dyad)
    True

    FTr   c              3   B   K   | ]  }t        |d d   z
          yw)r   Nr   )rM   r.   rt   s     r   rO   zcheck_dyad.<locals>.<genexpr>1  s      I(1ar
l3Is   Nr   )r   rR   r"   r%   )r)   rt   s    `r   
check_dyadr     sT    p aL^F3F{
6{c!fqj EIVCR[IIIIr   c                 6   d| v ryt        dd      }t        d      gt        |       z  }t        d | D              }	 t        |      D ]J  \  }}||k\  r||xx   |z  cc<   ||xx   |z  cc<   t	        |      dk(  s4t        |      t        |      fc S  |dz  }^)a4   Split a tuple of dyadic rationals into two children
    so that d_tup = 1/2*(child1 + child2).

    Here, d_tup, child1, and child2 have nonnegative dyadic rational elements,
    and each tuple sums to 1.

    Basis vectors such as d_tup = (0, 1, 0) will return no children, since they cannot be split.
    r   r`   r   c              3   &   K   | ]	  }d |z    yw)r   Nr`   rL   s     r   rO   zsplit.<locals>.<genexpr>H  s     &!!A#&ra   r   )r   r"   listr#   r[   r%   rm   format)rt   bitchild1child2indvals         r   splitr   6  s     	F{
1a.Cqk]3v;&F&v&&F
!&) 	4HCczss"ss"6{aV}eFm33	4 	q r   c                     t        |       st        dj                  |             i }t        |       g}|D ]&  }||vst	        |      ||<   |t        ||         z  }( |S )a9   Recursively split dyadic tuples to produce a DAG. A node
    can have multiple parents. Interior nodes in the DAG represent second-order cones
    which must be formed to represent the corresponding weighted geometric mean.

    Return a dictionary keyed by dyadic tuples. The values are a list of that tuple's children.
    The dictionary will allow us to re-use nodes whose tuple we have already seen, which
    reduces the number of second-order cones that need to be formed.
    We use an OrderedDict so that the root node is the first element of tree.keys().
    z-input must be a dyadic weight vector. got: {})rR   rm   r   r%   r   r   )rt   r*   todor   s       r   r!   r!   V  sp     &!HOOPVWXXD&M?D "D=AhDGDaM!D"
 Kr   c                 >    ddj                  d | D              z   dz   S )z: Use the string representation of objects in a tuple.
    (z, c              3   2   K   | ]  }t        |        y wr   )strrL   s     r   rO   zprettytuple.<locals>.<genexpr>q  s     -a3q6-rP   ))joinr   s    r   prettytupler   n  s#     -1---33r   c                 &    t        d | D              S )zS Get the maximum denominator in a sequence of ``Fraction`` and ``int`` objects
    c              3   F   K   | ]  }t        |      j                    y wr   )r   rG   rL   s     r   rO   z get_max_denom.<locals>.<genexpr>w  s     41x{&&4s   !)rp   )tups    r   get_max_denomr   t  s     4444r   c                     t        t        | j                               t        d      }d}|D ]C  }t        | |   t        d      }|t	        |      dz   z  }|D ]  }|dt	        |      z   dz   z  } E |S )z Print keys of a dictionary with children (expected to be a Sequence) indented underneath.

    Used for printing out trees of second order cones to represent weighted geometric means.

    T)keyreverse F
z  )sortedr   keysr   r   )r+   r   resultr   r2   childs         r   
prettydictr   z  s     $qvvx.mTBDF 7!C&mUC+c"T)) 	7Ed[//$66F	77 Mr   c                     t        |       sJ t        |       }t        t        |            dz
  }t	        d | D              dz
  }t        ||      S )a   Return a lower bound on the number of cones needed to represent the tuple.
        Based on two simple lower bounds.

    Examples
    --------
    >>> lower_bound((0,1,0))
    0
    >>> lower_bound((Fraction(1, 2), Fraction(1,2)))
    1
    >>> lower_bound((Fraction(1, 4), Fraction(1, 4), Fraction(1, 4), Fraction(1, 4)))
    3
    >>> lower_bound((Fraction(1,8), Fraction(7,8)))
    3
       c              3   .   K   | ]  }|d k7  rdnd   ywr   r   Nr`   rM   es     r   rO   zlower_bound.<locals>.<genexpr>  s     1Q16aq 1s   r   )rR   r   r"   binr[   rp   )rt   mdlb1lb2s       r   lower_boundr     sP     &!!!	v	B
c"g,q.C 1&1
1A
5CsC=r   c                 Z    t        d | D              }t        |      t        |       z
  |z
  S )z Return the number of cones in the tree beyond the known lower bounds.
        if it is zero, then we know the tuple can't be represented in fewer cones.
    c              3   ,   K   | ]  }|d k7  s	d  ywr   r`   r   s     r   rO   zover_bound.<locals>.<genexpr>  s     /Q1/s   
)r[   r"   r   )rt   r*   nonzeross      r   
over_boundr     s-     /f//Ht9{6**X55r   )   )r   F))__doc__rB   collectionsr   	fractionsr   numpyrX   cvxpy.atoms.affine.reshaper   cvxpy.atoms.affine.vstackr   cvxpy.constraints.second_orderr   cvxpy.expressions.variabler	   r   r3   r7   r9   r<   r>   boolrE   rI   rR   r   rq   ru   ro   r    r   rn   r   r   r!   r   r   r   r   r   r`   r   r   <module>r      s      #   . , . /8v3 	# 	
# 
Sd S4T 67 7"'D '@ U# U$ Up02BF*,@FE@045"26r   