
    bi                         d Z ddlZddlZddlmc mZ ddlmZ	 ddl
mZ  G d dej                        Z e       Z G d 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)performance_utils)unique_listc                       e Zd ZdZed        Zej                  d        Zd Z	d Z
d ZddZdd	Zd
efdZd Zd ZddZd Zej(                  d
efd       Zd
efdZd
efdZej6                  d
efd       Zy)	Canonicalz=
    An interface for objects that can be canonicalized.
    c                 f    t        | j                        dk(  st        d      | j                  d   S )N   z6'expr' is ambiguous, there should be only one argumentr   )lenargs
ValueErrorselfs    T/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/cvxpy/utilities/canonical.pyexprzCanonical.expr   s,    499~"UVVyy|    c                 "    | j                         S )zThe graph implementation of the object stored as a property.

        Returns:
            A tuple of (affine expression, [constraints]).
        )canonicalizer   s    r   canonical_formzCanonical.canonical_form$   s       ""r   c                     t        | j                  D cg c]  }|j                         D ]  }|  c}}      S c c}}w )z<Returns all the variables present in the arguments.
        )r   r
   	variables)r   argvars      r   r   zCanonical.variables/   s:      IIASA#SASAC 	CA   ;
c                     t        | j                  D cg c]  }|j                         D ]  }|  c}}      S c c}}w )z=Returns all the parameters present in the arguments.
        )r   r
   
parameters)r   r   params      r   r   zCanonical.parameters5   s;     "iiFsS^^5EFEUFUFH 	HFr   c                     t        | j                  D cg c]  }|j                         D ]  }|  c}}      S c c}}w )z<Returns all the constants present in the arguments.
        )r   r
   	constants)r   r   consts      r   r   zCanonical.constants;   s:     "iiEsS]]_EEUEUEG 	GEr   Nc                    g }| j                   D ]b  }t        |t              r0|D cg c]  }|j                  |       }}|j	                  |       C|j	                  |j                  |             d | j                  ||      S c c}w )N)r
   
id_objects)r
   
isinstancelist	tree_copyappendcopy)r   r    new_argsr   elemarg_lists         r   r#   zCanonical.tree_copyA   s|    99 	;C#t$CFG4DNN:6GG)j 9:	; yyh:y>>	 Hs   Bc                 
   |i n|}t        |       |v r|t        |          S || j                  }n#t        |      t        | j                        k(  sJ | j                         }| t	        |       ||z    S  t	        |       | S )aG  Returns a shallow copy of the object.

        Used to reconstruct an object tree.

        Parameters
        ----------
        args : list, optional
            The arguments to reconstruct the object. If args=None, use the
            current args of the object.

        Returns
        -------
        Expression
        )idr
   r	   get_datatype)r   r
   r    datas       r   r%   zCanonical.copyK   s     &-R:
d8z!bh''<99Dt9DII...}}4:t--4:t$$r   returnc                      y)z
        Determines whether the current atom is implemented in C++. This method should be
        overridden in derived atom classes that are not implemented in C++.
        T r   s    r   _supports_cppzCanonical._supports_cppg   s    
 r   c                 "    | j                         S )a  
        Called by copy.copy()
        Creates a shallow copy of the object, that is, the copied object refers to the same
        leaf nodes as the original object. Non-leaf nodes are recreated.
        Constraints keep their .id attribute, as it is used to propagate dual variables.

        Summary:
        ========
        Leafs:              Same object
        Constraints:        New object with same .id
        Other expressions:  New object with new .id
        )r%   r   s    r   __copy__zCanonical.__copy__n   s     yy{r   c                     t        | dd      }|	||v r||   S t        |       5  t        j                  | |      }ddd       t        | dd      t	        j
                         }|_        ||<   |S # 1 sw Y   8xY w)z
        Called by copy.deepcopy()
        Creates an independent copy of the object while maintaining the relationship between the
        nodes in the expression tree.
        r*   N)getattrDefaultDeepCopyContextManagerr%   deepcopyluget_idr*   )r   memocvxpy_idnewnew_ids        r   __deepcopy__zCanonical.__deepcopy__}   s     4t,H$4>!.t4 0mmD$/0tT4(4 DNJ0 0s   A22A;c                      y)zvReturns info needed to reconstruct the object besides the args.

        Returns
        -------
        list
        Nr0   r   s    r   r+   zCanonical.get_data   s     r   c                 :    t        d | j                  D              S )zaReturns all the atoms present in the args.

        Returns
        -------
        list
        c              3   J   K   | ]  }|j                         D ]  }|   y wN)atoms).0r   atoms      r   	<genexpr>z"Canonical.atoms.<locals>.<genexpr>   s"     MCM4M4Ms   !#)r   r
   r   s    r   rC   zCanonical.atoms   s     M499MMMr   c                     | j                   }| j                         }| j                  D ]0  }t        ||j	                               }|xr |j                         }2 ||d}|S )z
        Aggregates and caches metrics for expression trees in self.args. So far
        metrics include the maximum dimensionality ('max_ndim') and whether
        all sub-expressions support C++ ('all_support_cpp').

        )max_ndimall_support_cpp)ndimr1   r
   max	_max_ndim_all_support_cpp)r   rH   cpp_supportr   metricss        r   _aggregate_metricszCanonical._aggregate_metrics   sk     99((*99 	AC8S]]_5H%@#*>*>*@K	A
 !*
 r   c                 (    | j                         d   S )z@The maximum number of dimensions of the sub-expression.
        rH   rP   r   s    r   rL   zCanonical._max_ndim   s     &&(44r   c                 (    | j                         d   S )zS
        Returns True if all sub-expressions support C++, False otherwise.
        rI   rR   r   s    r   rM   zCanonical._all_support_cpp   s     &&():;;r   c                     t               rB   )NotImplementedErrorr   s    r   __str__zCanonical.__str__   s    !##r   rB   )NN)r.   N)__name__
__module____qualname____doc__propertyr   pulazypropr   r   r   r   r#   r%   boolr1   r3   r>   r+   rC   compute_oncedictrP   intrL   rM   abcabstractmethodstrrV   r0   r   r   r   r      s      
 [[# #CHG?%8t $N __D  (53 5
<$ < 	$ $ $r   r   )	metaclassc                   "    e Zd ZdZd Zd Zd Zy)r6   ze
    override custom __deepcopy__ implementation and call copy.deepcopy's implementation instead
    c                      || _         d | _        y rB   )itemr7   )r   rh   s     r   __init__z&DefaultDeepCopyContextManager.__init__   s    	r   c                     t        | j                  dt              | _        | j                  t        urd | j                  _        y y )Nr>   )r5   rh   _MISSINGr7   r>   r   s    r   	__enter__z'DefaultDeepCopyContextManager.__enter__   s3    		>8D==(%)DII" )r   c                 v    | j                   t        ur'| j                   | j                  _        t        | _         y y rB   )r7   rk   rh   r>   )r   exc_typeexc_valexc_tbs       r   __exit__z&DefaultDeepCopyContextManager.__exit__   s*    ==(%)]]DII"$DM )r   N)rW   rX   rY   rZ   ri   rl   rq   r0   r   r   r6   r6      s    *
%r   r6   )rZ   rb   r%   cvxpy.lin_ops.lin_utilslin_ops	lin_utilsr8   cvxpy.utilitiesr   r\   cvxpy.utilities.deterministicr   ABCMetar   objectrk   r6   r0   r   r   <module>ry      sD       $ $ 3 5k$#++ k$\ 8% %r   