
    bik?                     V   d Z ddlZddlmZ ddlmZmZ ddlZ	ddl
mZ ddlmc mZ ddlmc mZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZmZ dd	l m!Z" dd
l#m$Z$ ddl%m&Z& ddl'm(Z(m)Z) ddl*m+Z+  G d de      Z,ddZ- G d de,      Z. G d de.      Z/ G d de,      Z0d Z1d Z2d Z3y)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)reduce)ListTuple)AddExpression)AffAtom)conj)deep_flattenreshape)sum)
Constraint)DCPError)is_param_affineis_param_free)
Expressionc                   b     e Zd ZdZdZd
 fdZd Zd Zdee	e	f   fdZ
de	fdZde	fd	Z xZS )BinaryOperatorzW
    Base class for expressions involving binary operators. (other than addition)

    	BINARY_OPreturnc                 .    t         t        |   ||       y N)superr   __init__)selflh_exprh_exp	__class__s      ^/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/cvxpy/atoms/affine/binary_operators.pyr   zBinaryOperator.__init__1   s    nd,VV<    c                    g }| j                   D ]]  }t        |t        t        f      r&|j	                  d|j                         z   dz          ?|j	                  |j                                _ |d   dz   | j                  z   dz   |d   z   S )N()r       )args
isinstancer   DivExpressionappendnameOP_NAME)r   pretty_argsas      r   r(   zBinaryOperator.name4   s     	-A!m];<""3>C#78""1668,		-
 1~#dll2S8;q>IIr   c                 .    t        | j                  |      S )z3Applies the binary operator to the values.
        )r   OP_FUNCr   valuess     r   numericzBinaryOperator.numeric=   s     dllF++r   c                 v    t         j                  j                  | j                  d   | j                  d         S )z$Default to rules for times.
        r   r#   )usignmul_signr$   r   s    r   sign_from_argszBinaryOperator.sign_from_argsB   s)     vvtyy|TYYq\::r   c                     | j                   d   j                         xr | j                   d   j                         xs< | j                   d   j                         xr | j                   d   j                         S )z%Is the expression imaginary?
        r   r#   )r$   is_imagis_realr5   s    r   r8   zBinaryOperator.is_imagG   sd     		!$$&A499Q<+?+?+A @YYq\!!#>		!(<(<(>	@r   c                     | j                   d   j                         xs | j                   d   j                         xr= | j                   d   j                         xr | j                   d   j                          S )z*Is the expression complex valued?
        r   r#   )r$   
is_complexr8   r5   s    r   r;   zBinaryOperator.is_complexM   sg     		!'')FTYYq\-D-D-F D1%%'BDIIaL,@,@,BC	Dr   r   N)__name__
__module____qualname____doc__r)   r   r(   r0   r   boolr6   r8   r;   __classcell__r   s   @r   r   r   )   sP    
 G=J,
;dDj 1 ;
@ @DD Dr   r   MulExpressionc                     t        | |      S )zMatrix multiplication.)rD   )r   r   s     r   matmulrF   T   s    ((r   c                        e Zd ZdZdZej                  Zd Zd Z	de
edf   fdZ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efdZ fdZ	 dde
edf   de
ej,                  ee   f   fdZ xZS )rD   a  Matrix multiplication.

    The semantics of multiplication are exactly as those of NumPy's
    matmul function, except here multiplication by a scalar is permitted.
    MulExpression objects can be created by using the '*' operator of
    the Expression class.

    Parameters
    ----------
    lh_exp : Expression
        The left-hand side of the multiplication.
    rh_exp : Expression
        The right-hand side of the multiplication.
    @c                 v    |d   j                   dk(  s|d   j                   dk(  r|d   |d   z  S |d   |d   z  S )zMatrix multiplication.
        r    r#   )shaper.   s     r   r0   zMulExpression.numericl   sI     !9??b F1IOOr$9!9vay((!9vay((r   c                     | j                   d   j                  dkD  s| j                   d   j                  dkD  rt        d      y)z7Validate that the arguments can be multiplied together.r      r#   z3Multiplication with N-d arrays is not yet supportedN)r$   ndim
ValueErrorr5   s    r   validate_argumentsz MulExpression.validate_argumentst   s>    99Q<q DIIaL$5$5$9RSS %:r   r   .c                     t         j                  j                  | j                  d   j                  | j                  d   j                        S )8Returns the (row, col) shape of the expression.
        r   r#   )r2   rK   
mul_shapesr$   r5   s    r   shape_from_argszMulExpression.shape_from_argsy   s7     ww!!$))A,"4"4diil6H6HIIr   c                    t         j                  j                         rt| j                  d   }| j                  d   }|j	                         xs |j	                         xs2 t        |      xr t        |      xs t        |      xr t        |      S | j                  d   j	                         xs | j                  d   j	                         S )zpMultiplication is convex (affine) in its arguments only if one of
           the arguments is constant.
        r   r#   )r2   scopesdpp_scope_activer$   is_constantr   r   )r   xys      r   is_atom_convexzMulExpression.is_atom_convex~   s     88$$& 		!A		!A]]_7 >$Q'<M!,<>$Q'<M!,<? 99Q<++-K11I1I1KKr   c                 "    | j                         S )zAIf the multiplication atom is convex, then it is affine.
        r[   r5   s    r   is_atom_concavezMulExpression.is_atom_concave   s     ""$$r   c                      yz$Is the atom log-log convex?
        TrJ   r5   s    r   is_atom_log_log_convexz$MulExpression.is_atom_log_log_convex        r   c                      y)%Is the atom log-log concave?
        FrJ   r5   s    r   is_atom_log_log_concavez%MulExpression.is_atom_log_log_concave   s     r   c                 B    | j                   d|z
     j                         S );Is the composition non-decreasing in argument idx?
        r#   )r$   	is_nonnegr   idxs     r   is_incrzMulExpression.is_incr         yy3))++r   c                 B    | j                   d|z
     j                         S );Is the composition non-increasing in argument idx?
        r#   )r$   	is_nonposri   s     r   is_decrzMulExpression.is_decr   rl   r   c                    | j                   d   j                         s| j                   d   j                         rt        t        |   |      S |d   }|d   }| j                   d   j
                  }| j                   d   j
                  }t        | j                   d   j                        dk(  rst        | j                   d   j                        dk(  rNt        j                  |j                  dd            }t        j                  |j                  dd            }||gS t        j                  ||f      }t        | j                   d   j                  d         D ]C  }|||d| j                   d   j                  d   |d| j                   d   j                  d   f<   E t        j                  |      }t        | j                   d   j                        dk(  rdn| j                   d   j                  d   }t        j                  t        |      D cg c]!  }t        j                  |j                         # c}d      }||gS c c}w )a+  Gives the (sub/super)gradient of the atom w.r.t. each argument.

        Matrix expressions are vectorized, so the gradient is a matrix.

        Args:
            values: A list of numeric values for the arguments.

        Returns:
            A list of SciPy CSC sparse matrices or None.
        r   r#   Ncsc)r$   rX   r   rD   _gradsizelenrK   sp	csc_arrayr
   	dok_arrayrange
block_diagnp
atleast_2dT)
r   r/   XYDX_rowscolsDXDYkr   s
            r   rt   zMulExpression._grad   s    99Q<##%1)A)A)C3F;; 1I1I))A,##yy|   tyy|!!"a'C		!0B0B,Cq,HaiiA./BaiiA./B8O
 \\7D/*tyy|))!,- 	GAEFBq'$))A,$$Q'')ADIIaL,>,>q,A)AAB	G\\"		!**+q0qdiil6H6H6K]]dD1BMM!##.DeLBx Es   &IrK   c                    |d   }|d   }| j                   d   j                         rt        j                  |||      g fS | j                   d   j                         rt        j                  |||      g fS t        d      )  Multiply the linear expressions.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        shape : tuple
            The shape of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of constraints)
        r   r#   3Product of two non-constant expressions is not DCP.)r$   rX   lumul_expr	rmul_exprr   r   arg_objsrK   datalhsrhss         r   graph_implementationz"MulExpression.graph_implementation   s    ( qkqk99Q<##%KKS%0"55YYq\%%'LLc51266 " # #r   r   )r=   r>   r?   r@   r)   opmulr-   r0   rP   r   intrT   rA   r[   r^   ra   re   rk   rp   rt   loLinOpr   r   r   rB   rC   s   @r   rD   rD   Y   s     GffG)T
JsCx J
L L.% %
 
 
,d ,
,d ,
&R 6:#$S#X#	rxxj))	*#r   c                        e Zd ZdZdZd 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
 Zdeedf   fdZdefdZdefdZ	 ddeedf   deej&                  ee   f   fdZ xZS )multiplyz'Multiplies two expressions elementwise.*r   c                 X    | j                  ||      \  }}t        t        |   ||       y r   )	broadcastr   r   r   r   lh_exprrh_exprr   s      r   r   zmultiply.__init__   s)    >>'7;h&w8r   c                      y)zIs the atom log-log convex?TrJ   r5   s    r   ra   zmultiply.is_atom_log_log_convex       r   c                      y)zIs the atom log-log concave?TrJ   r5   s    r   re   z multiply.is_atom_log_log_concave  r   r   c                 r   | j                   d   j                         xs | j                   d   j                         xsz | j                   d   j                         xr | j                   d   j                         xs< | j                   d   j                         xr | j                   d   j                         S Nr   r#   )r$   rX   rh   ro   r5   s    r   is_atom_quasiconvexzmultiply.is_atom_quasiconvex  s    IIaL$$&D$))A,*B*B*DCIIaL""$A1)?)?)AC IIaL""$A1)?)?)A	Cr   c                     | j                   d   j                         xs | j                   d   j                         xs: t        d | j                   D              xs t        d | j                   D              S )Nr   r#   c              3   <   K   | ]  }|j                           y wr   )rh   .0args     r   	<genexpr>z0multiply.is_atom_quasiconcave.<locals>.<genexpr>  s      M2 #CMMOM2   c              3   <   K   | ]  }|j                           y wr   )ro   r   s     r   r   z0multiply.is_atom_quasiconcave.<locals>.<genexpr>  s      92 #CMMO92r   )r$   rX   allr5   s    r   is_atom_quasiconcavezmultiply.is_atom_quasiconcave  sp    IIaL$$&D$))A,*B*B*D2IL M2'+yyM2 J2258 92'+yy92 62	2r   c                     t        j                  |d         r|d   j                  |d         S t        j                  |d         r|d   j                  |d         S t        j                  |d   |d         S )z"Multiplies the values elementwise.r   r#   )rw   issparser   r|   r.   s     r   r0   zmultiply.numeric  sm    ;;vay!!9%%fQi00[[#!9%%fQi00;;vay&)44r   c           	      ,   t        j                  t        j                  | j                  d   j                  t        j
                  g             t        j                  | j                  d   j                  t        j
                  g                    y)z.Validate that the arguments are broadcastable.r   )dtyper#   N)r|   r   emptyr$   rK   r   r5   s    r   rP   zmultiply.validate_arguments  sV    
HHTYYq\''rxx|<HHTYYq\''rxx|<	
r   .c                     t        j                  | j                  d   j                  | j                  d   j                        S )z(Call np.broadcast on multiply arguments.r   r#   )r|   broadcast_shapesr$   rK   r5   s    r   rT   zmultiply.shape_from_args"  s1    ""499Q<#5#5tyy|7I7IJJr   c                     | j                   d   j                         xr | j                   d   j                         xs< | j                   d   j                         xr | j                   d   j                         S )z:Is the expression a positive semidefinite matrix?
        r   r#   r$   is_psdis_nsdr5   s    r   r   zmultiply.is_psd&  d     		!##%?$))A,*=*=*? A		!##%?$))A,*=*=*?	Ar   c                     | j                   d   j                         xr | j                   d   j                         xs< | j                   d   j                         xr | j                   d   j                         S )z:Is the expression a negative semidefinite matrix?
        r   r#   r   r5   s    r   r   zmultiply.is_nsd,  r   r   rK   c                     |d   }|d   }| j                   d   j                         rt        j                  ||      g fS | j                   d   j                         rt        j                  ||      g fS t	        d      )a  Multiply the expressions elementwise.

        Parameters
        ----------
        arg_objs : list
            LinExpr for each argument.
        shape : tuple
            The shape of the resulting expression.
        data :
            Additional data required by the atom.

        Returns
        -------
        tuple
            (LinOp for objective, list of exprraints)
        r   r#   r   )r$   rX   r   r   r   r   s         r   r   zmultiply.graph_implementation2  s|    ( qkqk99Q<##%KKS)2..YYq\%%'KKS)2.. " # #r   r<   r   )r=   r>   r?   r@   r)   r   rA   ra   re   r   r   r0   rP   r   r   rT   r   r   r   r   r   r   r   rB   rC   s   @r   r   r      s    1G9  CT C2d 25
KsCx KA AA A 6:#$S#X#	rxxj))	*#r   r   c                   "    e Zd ZdZdZej                  Zd fdZd Z	de
fdZde
fdZde
fdZdeed	f   fd
Z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e
fdZde
fdZde
fdZ	 ddeed	f   deej4                  ee   f   fdZ xZS )r&   zSDivision by scalar.

    Can be created by using the / operator of expression.
    /r   c                 X    | j                  ||      \  }}t        t        |   ||       y r   )r   r   r&   r   r   s      r   r   zDivExpression.__init__Z  s)    >>'7;mT+GW=r   c                     t        d      D ]1  }t        j                  ||         s||   j                         ||<   3 t	        j
                  |d   |d         S )z*Divides numerator by denominator.
        rM   r   r#   )rz   rw   r   toarrayr|   divide)r   r/   is      r   r0   zDivExpression.numeric^  sX     q 	0A{{6!9%"1I--/q		0 yyF1I..r   c                 z    | j                   d   j                         xr | j                   d   j                         S r   )r$   is_quadraticrX   r5   s    r   r   zDivExpression.is_quadraticf  s/    yy|((*Ityy|/G/G/IIr   c                 z    | j                   d   j                         xr | j                   d   j                         S )z/Can be a quadratic term if divisor is constant.r   r#   )r$   has_quadratic_termrX   r5   s    r   r   z DivExpression.has_quadratic_termi  s/    yy|..0OTYYq\5M5M5OOr   c                 z    | j                   d   j                         xr | j                   d   j                         S r   )r$   is_qpwarX   r5   s    r   r   zDivExpression.is_qpwam  s/    yy|##%D$))A,*B*B*DDr   .c                 4    | j                   d   j                  S )rR   r   )r$   rK   r5   s    r   rT   zDivExpression.shape_from_argsp  s     yy|!!!r   c                 <    | j                   d   j                         S )zeDivision is convex (affine) in its arguments only if
           the denominator is constant.
        r#   )r$   rX   r5   s    r   r[   zDivExpression.is_atom_convexu  s     yy|''))r   c                 "    | j                         S r   r]   r5   s    r   r^   zDivExpression.is_atom_concave{  s    ""$$r   c                      yr`   rJ   r5   s    r   ra   z$DivExpression.is_atom_log_log_convex~  rb   r   c                      y)rd   TrJ   r5   s    r   re   z%DivExpression.is_atom_log_log_concave  rb   r   c                 z    | j                   d   j                         xs | j                   d   j                         S )Nr#   r$   rh   ro   r5   s    r   r   z!DivExpression.is_atom_quasiconvex  s/    yy|%%'C499Q<+A+A+CCr   c                 "    | j                         S r   )r   r5   s    r   r   z"DivExpression.is_atom_quasiconcave  s    ''))r   c                     |dk(  r| j                   d   j                         S | j                   d   j                         S )rg   r   r#   r   ri   s     r   rk   zDivExpression.is_incr  9     !899Q<))++99Q<))++r   c                     |dk(  r| j                   d   j                         S | j                   d   j                         S )rn   r   r#   )r$   ro   rh   ri   s     r   rp   zDivExpression.is_decr  r   r   rK   c                 >    t        j                  |d   |d         g fS )r   r   r#   )r   div_expr)r   r   rK   r   s       r   r   z"DivExpression.graph_implementation  s"    & HQK!5r::r   r<   r   )r=   r>   r?   r@   r)   r|   r   r-   r   r0   rA   r   r   r   r   r   rT   r[   r^   ra   re   r   r   rk   rp   r   r   r   r   r   rB   rC   s   @r   r&   r&   Q  s    
 GiiG>/Jd JPD PE E"sCx "
* *% % 
 
DT D*d *,d ,,d , 6:;$S#X;	rxxj))	*;r   r&   c                 n    t        |       } t        |      }t        t        |       |      }t        |      S )a?  
    Return the standard inner product (or "scalar product") of (x,y).

    Parameters
    ----------
    x : Expression, int, float, NumPy ndarray, or nested list thereof.
        The conjugate-linear argument to the inner product.
    y : Expression, int, float, NumPy ndarray, or nested list thereof.
        The linear argument to the inner product.

    Returns
    -------
    expr : Expression
        The standard inner product of (x,y), conjugate-linear in x.
        We always have ``expr.shape == ()``.

    Notes
    -----
    The arguments ``x`` and ``y`` can be nested lists; these lists
    will be flattened independently of one another.

    For example, if ``x = [[a],[b]]`` and  ``y = [c, d]`` (with ``a,b,c,d``
    real scalars), then this function returns an Expression representing
    ``a * c + b * d``.
    )r	   r   r   	cvxpy_sum)rY   rZ   prods      r   vdotr     s0    4 	QAQADGQDT?r   c                     t        | |      S )z
    Alias for vdot.
    )r   rY   rZ   s     r   scalar_productr     s     1:r   c                 0   t        j                  |       } | j                  dkD  rt        d      t        j                  |      }|j                  dkD  rt        d      t	        | | j
                  dfd      } t	        |d|j
                  fd      }| |z  S )a+  
    Return the outer product of (x,y).

    Parameters
    ----------
    x : Expression, int, float, NumPy ndarray, or nested list thereof.
        Input is flattened if not already a vector.
        The linear argument to the outer product.
    y : Expression, int, float, NumPy ndarray, or nested list thereof.
        Input is flattened if not already a vector.
        The transposed-linear argument to the outer product.

    Returns
    -------
    expr : Expression
        The outer product of (x,y), linear in x and transposed-linear in y.
    r#   zx must be a 1-d array.zy must be a 1-d array.F)order)r   cast_to_constrN   rO   r
   ru   r   s     r   outerr     s    $ 	  #Avvz122  #Avvz122AFFA;c*AAqvv;c*Aq5Lr   )r   rD   )4r@   operatorr   	functoolsr   typingr   r   numpyr|   scipy.sparsesparserw   cvxpy.lin_ops.lin_oplin_opslin_opr   cvxpy.lin_ops.lin_utils	lin_utilsr   cvxpy.utilities	utilitiesr2   cvxpy.atoms.affine.add_exprr   cvxpy.atoms.affine.affine_atomr   cvxpy.atoms.affine.conjr   cvxpy.atoms.affine.reshaper	   r
   cvxpy.atoms.affine.sumr   r   cvxpy.constraints.constraintr   cvxpy.errorr   %cvxpy.expressions.constants.parameterr   r   cvxpy.expressions.expressionr   r   rF   rD   r   r&   r   r   r   rJ   r   r   <module>r      s          ! ! $ $  5 2 ( < 3 3   4(DW (DV)
Y#N Y#xY#} Y#x`;N `;F@r   