U
    ZÊ¹jm,  ã                   @   s¼   d 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mZmZ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 dd„ Zdd„ Zdd„ Zdd„ Zedd„ ƒZdS )z0Tools for constructing domains for expressions. é    )Úprod)Úsympify)Úpure_complex)Úordered)ÚZZÚQQÚZZ_IÚQQ_IÚEX)ÚComplexField)Ú	RealField)Úbuild_options)Úparallel_dict_from_basic)Úpublicc                    sŠ  d } } }}g }|j dkr(dd„ }ndd„ }| D ]²}|jrJ|jsæd}q4|jrj|rZ dS d}| |¡ q4t|ƒ}	|	rÈd}|	\}
}|
jr¢|jr¢|
jrš|js4d}q4qæd}|
jr¶| |
¡ |jræ| |¡ q4||ƒrà|rÚ dS d}q4 dS q4|�r tdd„ |D ƒƒnd	}|�rt| |ƒ\‰ }nh|�r2|�r2t|d
�‰ n>|�rDt	|d
�‰ n,|�sR|j
�rb|�r\tnt‰ n|�rltnt‰ ‡ fdd„| D ƒ}ˆ |fS )z?Handle simple domains, e.g.: ZZ, QQ, RR and algebraic domains. FTc                 S   s   | j o
| jS ©N©Z	is_numberÚis_algebraic©Úcoeff© r   úV/var/www/html/bwave/python/venv/lib/python3.8/site-packages/sympy/polys/constructor.pyÚ<lambda>   ó    z#_construct_simple.<locals>.<lambda>c                 S   s   dS )NFr   r   r   r   r   r      r   Nc                 s   s   | ]}|j V  qd S r   ©Z_prec©Ú.0Úcr   r   r   Ú	<genexpr>>   s     z$_construct_simple.<locals>.<genexpr>é5   ©Úprecc                    s   g | ]}ˆ   |¡‘qS r   )Ú
from_sympy)r   r   ©Údomainr   r   Ú
<listcomp>L   s     z%_construct_simple.<locals>.<listcomp>)Ú	extensionÚis_RationalÚ
is_IntegerÚis_FloatÚappendr   ÚmaxÚ_construct_algebraicr   r   Úfieldr	   r   r   r   )ÚcoeffsÚoptÚ	rationalsÚfloatsÚ	complexesZ
algebraicsÚfloat_numbersr   r   Ú
is_complexÚxÚyÚmax_precÚresultr   r"   r   Ú_construct_simple   sX    


r8   c           	         sÈ   ddl m} tƒ ‰‡ ‡fdd„‰ ˆ | ƒ}ttˆƒƒ‰|ˆddd�\‰}}tdd„ t|ˆƒD ƒƒ}t ˆ|f¡ˆj	 
¡  ‰‰‡‡fd	d
„|D ƒ}ttˆ|ƒƒ‰‡‡‡‡fdd„‰‡fdd
„|D ƒ}ˆ|fS )zDWe know that coefficients are algebraic so construct the extension. r   )Úprimitive_elementc                    sp   g }| D ]b}|j r"dt |¡f}n>|jr8dˆ |jƒf}n(|jrNdˆ |jƒf}nd|f}ˆ |¡ | |¡ q|S )NÚQú+Ú*Úe)r&   r   r!   Zis_AddÚargsZis_MulÚaddr)   )r>   ÚtreesÚaÚtree)Úbuild_treesÚextsr   r   rC   W   s    
z)_construct_algebraic.<locals>.build_treesT)ÚexÚpolysc                 s   s   | ]\}}|| V  qd S r   r   )r   ÚsÚextr   r   r   r   j   s     z'_construct_algebraic.<locals>.<genexpr>c                    s   g | ]}ˆ j  |ˆt¡‘qS r   )ÚdtypeÚ	from_listr   )r   Úh)r#   Úgr   r   r$   n   s     z(_construct_algebraic.<locals>.<listcomp>c                    sz   | \}}|dkr"ˆj  |gˆt¡S |dkrDt‡ fdd„|D ƒˆjƒS |dkrbt‡ fdd„|D ƒƒS |dkrrˆ| S t‚d S )Nr:   r;   c                 3   s   | ]}ˆ |ƒV  qd S r   r   ©r   rA   ©Úconvert_treer   r   r   v   s     z=_construct_algebraic.<locals>.convert_tree.<locals>.<genexpr>r<   c                 3   s   | ]}ˆ |ƒV  qd S r   r   rM   rN   r   r   r   x   s     r=   )rI   rJ   r   ÚsumÚzeror   ÚRuntimeError)rB   Úopr>   )rO   r#   Úexts_maprL   r   r   rO   q   s    z*_construct_algebraic.<locals>.convert_treec                    s   g | ]}ˆ |ƒ‘qS r   r   )r   rB   rN   r   r   r$   ~   s     )Zsympy.polys.numberfieldsr9   ÚsetÚlistr   rP   Úzipr   Zalgebraic_fieldÚrepZto_listÚdict)	r-   r.   r9   r@   ÚspanÚHÚrootZexts_domr7   r   )rC   rO   r#   rD   rT   rL   r   r+   Q   s    r+   c                 C   s�  g g  }}| D ]$}|  ¡ \}}| |¡ | |¡ qt|| ƒ\}}|sLdS |jdkr˜tdd„ |D ƒƒrldS tƒ }	|D ] }
|
j}|	|@ rŽ dS |	|O }	qvt|ƒ}t|ƒd }|d|… }||d… }|jrÐd}n8dd|  }}|D ]$}t|ƒdk� sü||krâd} �qqâtƒ } |�sbt	||ƒD ]@\}}|| }| 
¡ D ]$\}}|| }|  |¡ |||< �q6�qn:t	||ƒD ].\}}|  t| ¡ ƒ¡ |  t| ¡ ƒ¡ �qld } }}g }| D ] }|j�rÊ|j�sNd}n„|j�râd}| |¡ nlt|ƒ}|dk	�r°d}|\}}|j�r&|j�r&|j�r |j�sNd}n(d}|j�r<| |¡ |j�r°| |¡ �q°|�rjtd	d„ |D ƒƒnd
}|�r†|�r†t|d�}n:|�r˜t|d�}n(|�r°|�rªt}nt}n|�r¼t}nt}g }|�s|j|Ž }|D ]6}| 
¡ D ]\}}| |¡||< �qä| ||ƒ¡ �qØnv|j|Ž }t	||ƒD ]`\}}| 
¡ D ]\}}| |¡||< �q6| 
¡ D ]\}}| |¡||< �qX| |||fƒ¡ �q&||fS )z<Handle composite domains, e.g.: ZZ[X], QQ[X], ZZ(X), QQ(X). Nc                 s   s   | ]}|j o|jV  qd S r   r   )r   Úgenr   r   r   r   ’   s     z'_construct_composite.<locals>.<genexpr>é   TF)r   é   c                 s   s   | ]}|j V  qd S r   r   r   r   r   r   r   ×   s     r   r   )Zas_numer_denomr)   r   Ú	compositeÚanyrU   Zfree_symbolsÚlenr,   rW   Úitemsr?   ÚupdaterV   Úvaluesr&   r'   r(   r   r*   r   r   r	   r   r   r   Z	poly_ringr!   Z
frac_field)r-   r.   ZnumersZdenomsr   ZnumerÚdenomrF   ZgensZall_symbolsr]   ÚsymbolsÚnÚkÚ	fractionsZzerosZmonomr/   r0   r1   r2   r3   r4   r5   r6   Zgroundr7   r#   r   r   r   Ú_construct_compositeƒ   s®    








rk   c                 C   s,   t g  }}| D ]}| | |¡¡ q||fS )z6The last resort case, i.e. use the expression domain. )r
   r)   r!   )r-   r.   r#   r7   r   r   r   r   Ú_construct_expression   s    
rl   c                 K   s  t |ƒ}t| dƒrLt| tƒrF| s,g g  }}qJttt|  ¡ ƒŽ ƒ\}}qR| }n| g}ttt|ƒƒ}t	||ƒ}|dk	r”|dk	r„|\}}qÎt
||ƒ\}}n:|jdkr¤d}n
t||ƒ}|dk	rÀ|\}}nt
||ƒ\}}t| dƒ�rt| tƒrú|ttt||ƒƒƒfS ||fS n||d fS dS )aT	  Construct a minimal domain for a list of expressions.

    Explanation
    ===========

    Given a list of normal SymPy expressions (of type :py:class:`~.Expr`)
    ``construct_domain`` will find a minimal :py:class:`~.Domain` that can
    represent those expressions. The expressions will be converted to elements
    of the domain and both the domain and the domain elements are returned.

    Parameters
    ==========

    obj: list or dict
        The expressions to build a domain for.

    **args: keyword arguments
        Options that affect the choice of domain.

    Returns
    =======

    (K, elements): Domain and list of domain elements
        The domain K that can represent the expressions and the list or dict
        of domain elements representing the same expressions as elements of K.

    Examples
    ========

    Given a list of :py:class:`~.Integer` ``construct_domain`` will return the
    domain :ref:`ZZ` and a list of integers as elements of :ref:`ZZ`.

    >>> from sympy import construct_domain, S
    >>> expressions = [S(2), S(3), S(4)]
    >>> K, elements = construct_domain(expressions)
    >>> K
    ZZ
    >>> elements
    [2, 3, 4]
    >>> type(elements[0])  # doctest: +SKIP
    <class 'int'>
    >>> type(expressions[0])
    <class 'sympy.core.numbers.Integer'>

    If there are any :py:class:`~.Rational` then :ref:`QQ` is returned
    instead.

    >>> construct_domain([S(1)/2, S(3)/4])
    (QQ, [1/2, 3/4])

    If there are symbols then a polynomial ring :ref:`K[x]` is returned.

    >>> from sympy import symbols
    >>> x, y = symbols('x, y')
    >>> construct_domain([2*x + 1, S(3)/4])
    (QQ[x], [2*x + 1, 3/4])
    >>> construct_domain([2*x + 1, y])
    (ZZ[x,y], [2*x + 1, y])

    If any symbols appear with negative powers then a rational function field
    :ref:`K(x)` will be returned.

    >>> construct_domain([y/x, x/(1 - y)])
    (ZZ(x,y), [y/x, -x/(y - 1)])

    Irrational algebraic numbers will result in the :ref:`EX` domain by
    default. The keyword argument ``extension=True`` leads to the construction
    of an algebraic number field :ref:`QQ(a)`.

    >>> from sympy import sqrt
    >>> construct_domain([sqrt(2)])
    (EX, [EX(sqrt(2))])
    >>> construct_domain([sqrt(2)], extension=True)  # doctest: +SKIP
    (QQ<sqrt(2)>, [ANP([1, 0], [1, 0, -2], QQ)])

    See also
    ========

    Domain
    Expr
    Ú__iter__NFr   )r   ÚhasattrÚ
isinstancerY   rV   rW   rc   Úmapr   r8   rl   r`   rk   )Úobjr>   r.   Zmonomsr-   r7   r#   r   r   r   Úconstruct_domain
  s2    S








rr   N)Ú__doc__Úmathr   Z
sympy.corer   Zsympy.core.evalfr   Zsympy.core.sortingr   Zsympy.polys.domainsr   r   r   r	   r
   Z sympy.polys.domains.complexfieldr   Zsympy.polys.domains.realfieldr   Zsympy.polys.polyoptionsr   Zsympy.polys.polyutilsr   Zsympy.utilitiesr   r8   r+   rk   rl   rr   r   r   r   r   Ú<module>   s    B2}
