
    gq*                    "   d Z ddlmZ ddlmZ ee   Zd ZddZd Z	d Z
d Zd	 Zd
 Zd Z G d d      Z G d de      Z G d de      Z G d de      Z G d de      Zeej(                  d<   eej(                  d<   eej(                  d<   y)zLogic expressions handling

NOTE
----

at present this is mainly needed for facts.py, feel free however to improve
this stuff for general purpose.
    )annotations)Optionalc                J    dx}}| D ]  }|du r|r yd}|du r|r yd} y |S )zReturn True if all args are True, False if they
    are all False, else None.

    >>> from sympy.core.logic import _torf
    >>> _torf((True, True))
    True
    >>> _torf((False, False))
    False
    >>> _torf((True, False))
    FTN )argssawTsawFas       E/var/www/openai/venv/lib/python3.12/site-packages/sympy/core/logic.py_torfr      sF     D49D%ZD  K    c                <    d}| D ]  }|du r| y|r|r yd} | S )a  Return True if all args are True, None if there is any None else False
    unless ``quick_exit`` is True (then return None as soon as a second False
    is seen.

     ``_fuzzy_group`` is like ``fuzzy_and`` except that it is more
    conservative in returning a False, waiting to make sure that all
    arguments are True or False and returning None if any arguments are
    None. It also has the capability of permiting only a single False and
    returning None if more than one is seen. For example, the presence of a
    single transcendental amongst rationals would indicate that the group is
    no longer rational; but a second transcendental in the group would make the
    determination impossible.


    Examples
    ========

    >>> from sympy.core.logic import _fuzzy_group

    By default, multiple Falses mean the group is broken:

    >>> _fuzzy_group([False, False, True])
    False

    If multiple Falses mean the group status is unknown then set
    `quick_exit` to True so None can be returned when the 2nd False is seen:

    >>> _fuzzy_group([False, False, True], quick_exit=True)

    But if only a single False is seen then the group is known to
    be broken:

    >>> _fuzzy_group([False, True, True], quick_exit=True)
    False

    FTNr   )r   
quick_exit	saw_otherr
   s       r   _fuzzy_groupr   +   s=    J I99)	  =r   c                (    | y| dv rt        |       S y)a  Return True, False or None according to x.

    Whereas bool(x) returns True or False, fuzzy_bool allows
    for the None value and non-false values (which become None), too.

    Examples
    ========

    >>> from sympy.core.logic import fuzzy_bool
    >>> from sympy.abc import x
    >>> fuzzy_bool(x), fuzzy_bool(None)
    (None, None)
    >>> bool(x), bool(None)
    (True, False)

    N)TF)bool)xs    r   
fuzzy_boolr   \   s"    " 	yMAw r   c                D    d}| D ]  }t        |      }|du r y|s|} |S )a  Return True (all True), False (any False) or None.

    Examples
    ========

    >>> from sympy.core.logic import fuzzy_and
    >>> from sympy import Dummy

    If you had a list of objects to test the commutivity of
    and you want the fuzzy_and logic applied, passing an
    iterator will allow the commutativity to only be computed
    as many times as necessary. With this list, False can be
    returned after analyzing the first symbol:

    >>> syms = [Dummy(commutative=False), Dummy()]
    >>> fuzzy_and(s.is_commutative for s in syms)
    False

    That False would require less work than if a list of pre-computed
    items was sent:

    >>> fuzzy_and([s.is_commutative for s in syms])
    False
    TFr   r   rvais      r   	fuzzy_andr   s   s5    4 
B^;B  Ir   c                    | | S |  S )z
    Not in fuzzy logic

    Return None if `v` is None else `not v`.

    Examples
    ========

    >>> from sympy.core.logic import fuzzy_not
    >>> fuzzy_not(True)
    False
    >>> fuzzy_not(None)
    >>> fuzzy_not(False)
    True

    r   )vs    r   	fuzzy_notr      s    " 	yur   c                H    d}| D ]  }t        |      }|du r y|du s|} |S )a  
    Or in fuzzy logic. Returns True (any True), False (all False), or None

    See the docstrings of fuzzy_and and fuzzy_not for more info.  fuzzy_or is
    related to the two by the standard De Morgan's law.

    >>> from sympy.core.logic import fuzzy_or
    >>> fuzzy_or([True, False])
    True
    >>> fuzzy_or([True, None])
    True
    >>> fuzzy_or([False, False])
    False
    >>> print(fuzzy_or([False, None]))
    None

    FTr   r   s      r   fuzzy_orr       s9    $ 
B^:;B  Ir   c                d    dx}}| D ]   }t        |      }|r|dz  }|du r|dz  }  y |dz  dk(  S )zReturn None if any element of args is not True or False, else
    True (if there are an odd number of True elements), else False.r      FN   r   )r   tfr
   r   s        r   	fuzzy_xorr&      sO     IA]FA5[FA  q5A:r   c                *    t        t        |             S )zMReturn False if all args are True, True if they are all False,
    else None.)r   r   r   s    r   
fuzzy_nandr)      s     Yt_%%r   c                  d    e Zd ZU dZi Zded<   d Zd Zd Zd Z	d Z
d	 Zd
 Zd ZeZed        Zy)LogiczLogical expressionzdict[str, type[Logic]]	op_2classc                >    t         j                  |       }||_        |S N)object__new__r   )clsr   objs      r   r0   zLogic.__new__   s    nnS!
r   c                    | j                   S r.   r(   selfs    r   __getnewargs__zLogic.__getnewargs__   s    yyr   c                l    t        t        |       j                  ft        | j                        z         S r.   )hashtype__name__tupler   r4   s    r   __hash__zLogic.__hash__   s(    T$Z((*U499-==>>r   c                `    t        |t        |             sy| j                  |j                  k(  S )NF
isinstancer9   r   r
   bs     r   __eq__zLogic.__eq__   s&    !T!W%66QVV##r   c                `    t        |t        |             sy| j                  |j                  k7  S )NTr>   r@   s     r   __ne__zLogic.__ne__   s&    !T!W%66QVV##r   c                .    | j                  |      dk(  ryy)NTF)__cmp__)r5   others     r   __lt__zLogic.__lt__   s    <<"$r   c                    t        |       t        |      ur)t        t        |             }t        t        |            }n| j                  }|j                  }||kD  ||k  z
  S r.   )r9   strr   )r5   rH   r
   rA   s       r   rG   zLogic.__cmp__   sR    :T%[(DJADK A		A

AA!a%  r   c                z    | j                   j                  ddj                  d | j                  D              dS )N(z, c              3  2   K   | ]  }t        |        y wr.   )rK   ).0r
   s     r   	<genexpr>z Logic.__str__.<locals>.<genexpr>  s     $?YSVYs   ))	__class__r:   joinr   r4   s    r   __str__zLogic.__str__	  s1    >>2299$?TYY$??A 	Ar   c                   d}d}| j                         D ]  }|dv r'|t        d|d|d      |t        d|z        |}.d|v sd|v rt        d	      |d
   dk(  r't        |      dk(  rt        d      t        |dd       }|rt	        j
                  |   ||      }d}|t        d|d|d      |} |t        d| z        |t        d| z        |S )znLogic from string with space around & and | but none after !.

           e.g.

           !a & b | c
        Nz&|zdouble op forbidden: " "z+%s cannot be in the beginning of expression&|z#& and | must have space around themr   !r"   zdo not include space after "!"zmissing op between "z" and "z#premature end-of-expression in "%s"z"%s" is empty)split
ValueErrorlenNotr+   r,   )textlexprschedopterms       r   
fromstringzLogic.fromstring  s.    JJLDt|&$:>HJ J=$ELN Nd{cTk !FGGAw#~t9>$%EFF48} 0=   :?FH H E; !@ BTIJJ=_t344 r   N)r:   
__module____qualname____doc__r,   __annotations__r0   r6   r<   rB   rD   rI   rG   rT   __repr__staticmethodrc   r   r   r   r+   r+      sR    (*I%*
?$$
!A H/ /r   r+   c                  "    e Zd Zd Zed        Zy)
AndOr_Basec                   g }|D ]7  }|| j                   k(  r|c S || j                    k(  r'|j                  |       9 t        t        | j	                  |            t
              }|D ]  }t        |      |v s| j                   c S  t        |      dk(  r|j                         S t        |      dk(  r| j                    S t        j                  | g| S )N)keyr"   r   )	op_x_notxappendsortedsetflattenr8   r^   r]   popr+   r0   )r1   r   bargsr
   s       r   r0   zAndOr_Base.__new__D  s    ACMM!3==()LLO  c#++e,-48A1v~}}$  t9>88:Y!^}}$$}}S(4((r   c                   t        |      }g }	 	 |j                  d      }t        |t              r(t        ||       r|j                  |j                         K|j                  |       \# t        $ r Y nw xY wt        |      }|S Nr   )	listrs   
IndexErrorr?   r+   extendr   ro   r;   )r1   r   
args_queueresargs        r   rr   zAndOr_Base.flattenZ  s     $Z
 nnQ' #u%c3'%%chh/JJsO    Szs   A+ +	A76A7N)r:   rd   re   r0   classmethodrr   r   r   r   rk   rk   B  s    ),  r   rk   c                      e Zd ZdZd Zd Zy)AndFc                ^    t        | j                  D cg c]  }t        |       c} S c c}w r.   )Orr   r^   r5   r
   s     r   _eval_propagate_notzAnd._eval_propagate_notr  s'    DII.IqCFI.//.   *c                   t        | j                        D ]  \  }}t        |t              s| j                  d | | j                  |dz   d  z   }|j                  D cg c]  }t	        ||fz     }}t        t        |            D ],  }t        ||   t              s||   j                         ||<   . t        | }|c S  | S c c}w )Nr"   )		enumerater   r?   r   r   ranger]   r+   expand)r5   ir|   arestr
   ortermsjr{   s           r   r   z
And.expandw  s      		*FAs#r"		"1		!a%&(999<BA3!/Bs7|,A!'!*e4%,QZ%6%6%8
 - 'l
 +  Cs   CN)r:   rd   re   rn   r   r   r   r   r   r   r   o  s    I0
r   r   c                      e Zd ZdZd Zy)r   Tc                ^    t        | j                  D cg c]  }t        |       c} S c c}w r.   )r   r   r^   r   s     r   r   zOr._eval_propagate_not  s'    TYY/YSVY/00/r   N)r:   rd   re   rn   r   r   r   r   r   r     s    I1r   r   c                  "    e Zd Zd Zed        Zy)r^   c                   t        |t              rt        j                  | |      S t        |t              r| S t        |t
              r|j                  d   S t        |t              r|j                         }|S t        d|      )Nr   zNot: unknown argument )	r?   rK   r+   r0   r   r^   r   r   r\   )r1   r|   s     r   r0   zNot.__new__  ss    c3==c**T"7NS!88A;U#))+CJ 3@AAr   c                     | j                   d   S rv   r(   r4   s    r   r|   zNot.arg  s    yy|r   N)r:   rd   re   r0   propertyr|   r   r   r   r^   r^     s    B"  r   r^   rX   rY   rZ   N)F)rf   
__future__r   typingr   r   	FuzzyBoolr   r   r   r   r   r    r&   r)   r+   rk   r   r   r^   r,   r   r   r   <module>r      s    #  TN	4.b.!H.8&` `F* *Z* 41 1% 0    r   