� ��g������dZddlmZddlmZmZmZmZddlm Z ddl m Z ddl m Z ddlmZddlmZmZdd lmZmZdd lmZmZdd lmZdd lmZdd lmZmZddl m!Z!ddl"m#Z#m$Z$m%Z%ddl&m'Z'm(Z(ddl)m*Z*d�Z+eGd�de ����Z,Gd�de,��Z-Gd�de-e���Z.Gd�de-e���Z/e.��Z0e/��Z1e0e_0e1e_1d�e#e2<Gd�dee,��Z3Gd�d ee3��Z4Gd!�d"ee3��Z5Gd#�d$e3��Z6Gd%�d&e3��Z7Gd'�d(e3��Z8Gd)�d*e3��Z9Gd+�d,e3��Z:Gd-�d.e3��Z;Gd/�d0e3��Z<Gd1�d2e3��Z=Gd3�d4e3��Z>d5�Z?d6�Z@d7�ZAd8�ZBd9�ZCd:�ZDdkd<�ZEdkd=�ZFdld?�ZGdld@�ZHdA�ZIdkdB�ZJdC�ZKdD�ZLdE�ZMdF�ZNdG�ZOdH�ZPdI�ZQe(ZRdkdJ�ZSdK�ZTdL�ZUdM�ZVdN�ZWdO�ZXdP�ZYdQ�ZZdR�Z[dS�Z\dmdU�Z]dV�Z^dmdW�Z_dX�Z`dY�ZadZ�Zbd[�Zcd\�Zdd]�Zednd^�Zfd_�Zgd`�Zhda�Zi dodb�Zjdc�Zkdd�Zle de���Zme df���Zne dg���Zoe dh���Zpdi�Zqe4e5e7e8e9e6e:e=fZrdj�ZsdTS)pz" Boolean algebra module for SymPy �)� defaultdict)�chain� combinations�product� permutations)�Add)�Basic)�cacheit)�Tuple)�sympify_method_args�sympify_return)� Application� Derivative)� BooleanKind� NumberKind)�Number)� LatticeOp)� Singleton�S)�ordered)�_sympy_converter�_sympify�sympify)�sift�ibin)� filldedentc���ddlm}|dkrtS|dkrtSt ||��r|j}|�|S|rtntSt |t ��r|Std|z���)aLike ``bool``, return the Boolean value of an expression, e, which can be any instance of :py:class:`~.Boolean` or ``bool``. Examples ======== >>> from sympy import true, false, nan >>> from sympy.logic.boolalg import as_Boolean >>> from sympy.abc import x >>> as_Boolean(0) is false True >>> as_Boolean(1) is true True >>> as_Boolean(x) x >>> as_Boolean(2) Traceback (most recent call last): ... TypeError: expecting bool or Boolean, not `2`. >>> as_Boolean(nan) Traceback (most recent call last): ... TypeError: expecting bool or Boolean, not `nan`. r)�SymbolTFNz$expecting bool or Boolean, not `%s`.)�sympy.core.symbolr�true�false� isinstance�is_zero�Boolean� TypeError)�er�zs �c/home/asafur/pinokio/api/open-webui.git/app/env/lib/python3.11/site-packages/sympy/logic/boolalg.py� as_Booleanr)s���4)�(�(�(�(�(��D�y�y�� ��E�z�z�� ��!�V���$� �I�� �9��H��#�u�u�t�#��!�W������ �:�Q�>� ?� ?�?�c�@�eZdZdZdZeZedge��d���Z e Z edge��d���Z e Z d�Z edge��d���Zedge��d���ZeZeZedge��d ���ZeZd �Zdd �Zd �Zed���Zd�ZdS)r$zDA Boolean object is an object for which logic operations make sense.�)�otherr$c�"�t||��S�N��And��selfr-s r(�__and__zBoolean.__and__H����4����r*c�"�t||��Sr/)�Orr2s r(�__or__zBoolean.__or__Ns���$����r*c� �t|��S)zOverloading for ~��Not�r3s r(� __invert__zBoolean.__invert__Ts���4�y�y�r*c�"�t||��Sr/��Impliesr2s r(� __rshift__zBoolean.__rshift__Xs���t�U�#�#�#r*c�"�t||��Sr/r?r2s r(� __lshift__zBoolean.__lshift__\s���u�d�#�#�#r*c�"�t||��Sr/)�Xorr2s r(�__xor__zBoolean.__xor__cr5r*c�.�ddlm}ddlm}|�|��s|�|��rt d���|���|���ko&|tt||������ S)a� Returns ``True`` if the given formulas have the same truth table. For two formulas to be equal they must have the same literals. Examples ======== >>> from sympy.abc import A, B, C >>> from sympy import And, Or, Not >>> (A >> B).equals(~B >> ~A) True >>> Not(And(A, B, C)).equals(And(Not(A), Not(B), Not(C))) False >>> Not(And(A, Not(A))).equals(Or(B, Not(B))) False r)� satisfiable�� Relationalzhandling of relationals) �sympy.logic.inferencerH�sympy.core.relationalrJ�has�NotImplementedError�atomsr;� Equivalent)r3r-rHrJs r(�equalszBoolean.equalsis���$ 6�5�5�5�5�5�4�4�4�4�4�4� �8�8�J� � � A�5�9�9�Z�#8�#8� A�%�&?�@�@� @��z�z�|�|�u�{�{�}�}�,�:�� �C� �4�� 7� 7�8�8�9�9� 9� :r*Tc��|Sr/r,�r3�simplifys r(�to_nnfzBoolean.to_nnf����� r*c��ddlm}ddlm}|j}t |��dk�r|���}|jtur�i}|� |��D]~}|||��dvrn|� ��}|tj tj tjfvr|�|��||<�bt!t#d������|�|��}|j|jkr|���S|� ��S|� ��St!d���)a� Rewrites Boolean expression in terms of real sets. Examples ======== >>> from sympy import Symbol, Eq, Or, And >>> x = Symbol('x', real=True) >>> Eq(x, 0).as_set() {0} >>> (x > 0).as_set() Interval.open(0, oo) >>> And(-2 < x, x < 2).as_set() Interval.open(-2, 2) >>> Or(x < -2, 2 < x).as_set() Union(Interval.open(-oo, -2), Interval.open(2, oo)) r)� periodicityrI�)rNz� as_set is not implemented for relationals with periodic solutions zGSorry, as_set has not yet been implemented for multivariate expressions)�sympy.calculus.utilrXrLrJ� free_symbols�len�pop�kindrrO� _eval_as_setr�EmptySet� UniversalSet�Reals� as_relationalrNr�subs�func�as_set) r3rXrJ�free�x�reps�r�s�news r(rfzBoolean.as_set�s`��& 4�3�3�3�3�3�4�4�4�4�4�4�� �� �t�9�9��>�>���� � �A��v��#�#������J�/�/� "� "�A�"�{�1�a�(�(� �9�9��N�N�,�,�����Q�^�Q�W� E�E�E�&'�o�o�a�&8�&8�D��G�$�1�*�> �3!�3!�"�"�"� :��i�i��o�o���8�t�y�(�(��:�:�<�<�'��+�+�-�-�-��$�$�&�&� &�%�'5�6�6� 6r*c�f���ddlm�m�t��j��fd�|jD���S)Nr��Eq�Nec�^��g|])}|js|jst|��f���"|j��*Sr,)� is_Boolean� is_Symbolr"�binary_symbols)�.0�irorps ��r(� <listcomp>z*Boolean.binary_symbols.<locals>.<listcomp>�sR���7�7�7�!��l�7�./�k�7�(��R��H�5�5�7�Q�-�7�7�7r*)rLrorp�set�union�args)r3rorps @@r(rtzBoolean.binary_symbols�s]����0�0�0�0�0�0�0�0��s�u�u�{�7�7�7�7�7�t�y�7�7�7�8� 8r*c�V�ddlm}|||��}|durtS|durtSdS)Nr)�askTF)�sympy.assumptionsr|r r!)r3� assumptionsr|�rets r(� _eval_refinezBoolean._eval_refine�sF��)�)�)�)�)�)��c�$� �$�$�� �$�;�;��K� �E�\�\��L��tr*N�T)�__name__� __module__� __qualname__�__doc__� __slots__rr^r �NotImplementedr4�__rand__r8�__ror__r=rArC� __rrshift__� __rlshift__rF�__rxor__rQrUrf�propertyrtr�r,r*r(r$r$@s�������N�N��I� �D��^�)�*�N�;�;� � �<�;� ��H��^�)�*�N�;�;���<�;���G�����^�)�*�N�;�;�$�$�<�;�$��^�)�*�N�;�;�$�$�<�;�$��K��K��^�)�*�N�;�;� � �<�;� ��H�:�:�:�4����/6�/6�/6�b�8�8��X�8� ����r*r$c��eZdZdZdZdZdZd�Zd�Ze d���Z d d�Z e Z e Z e Ze Ze Ze Ze Ze Ze Ze Ze Ze Ze Zd �ZeZeZeZd �ZdS) � BooleanAtomzQ Base class of :py:class:`~.BooleanTrue` and :py:class:`~.BooleanFalse`. T� c��|Sr/r,�r3�a�kws r(rTzBooleanAtom.simplify����� r*c��|Sr/r,r�s r(�expandzBooleanAtom.expand�r�r*c��|Sr/r,r<s r(� canonicalzBooleanAtom.canonical�rVr*Nc� �td���)Nz(BooleanAtom not allowed in this context.)r%r2s r(�_noopzBooleanAtom._noop�s���B�C�C�Cr*c�:�ttd������Nz� A Boolean argument can only be used in Eq and Ne; all other relationals expect real expressions. �r%rr2s r(�__lt__zBooleanAtom.__lt__��%��� �$ � � ��� r*c ��|Sr/r,)r3�kwargss r(�_eval_simplifyzBooleanAtom._eval_simplify�r�r*r/)r�r�r�r�rr�is_Atom� _op_priorityrTr�r�r�r��__add__�__radd__�__sub__�__rsub__�__mul__�__rmul__�__pow__�__rpow__� __truediv__� __rtruediv__�__mod__�__rmod__� _eval_powerr��__le__�__gt__�__ge__r�r,r*r(r�r��s����������J��G��L�����������X��D�D�D�D��G��H��G��H��G��H��G��H��K��L��G��H��K�����F� �F� �F�����r*r�c�J��eZdZdZd�Zd�Z�fd�Zed���Zd�Z �xZ S)� BooleanTruea� SymPy version of ``True``, a singleton that can be accessed via ``S.true``. This is the SymPy version of ``True``, for use in the logic module. The primary advantage of using ``true`` instead of ``True`` is that shorthand Boolean operations like ``~`` and ``>>`` will work as expected on this class, whereas with True they act bitwise on 1. Functions in the logic module will return this class when they evaluate to true. Notes ===== There is liable to be some confusion as to when ``True`` should be used and when ``S.true`` should be used in various contexts throughout SymPy. An important thing to remember is that ``sympify(True)`` returns ``S.true``. This means that for the most part, you can just use ``True`` and it will automatically be converted to ``S.true`` when necessary, similar to how you can generally use 1 instead of ``S.One``. The rule of thumb is: "If the boolean in question can be replaced by an arbitrary symbolic ``Boolean``, like ``Or(x, y)`` or ``x > 1``, use ``S.true``. Otherwise, use ``True``" In other words, use ``S.true`` only on those contexts where the boolean is being used as a symbolic representation of truth. For example, if the object ends up in the ``.args`` of any expression, then it must necessarily be ``S.true`` instead of ``True``, as elements of ``.args`` must be ``Basic``. On the other hand, ``==`` is not a symbolic operation in SymPy, since it always returns ``True`` or ``False``, and does so in terms of structural equality rather than mathematical, so it should return ``True``. The assumptions system should use ``True`` and ``False``. Aside from not satisfying the above rule of thumb, the assumptions system uses a three-valued logic (``True``, ``False``, ``None``), whereas ``S.true`` and ``S.false`` represent a two-valued logic. When in doubt, use ``True``. "``S.true == True is True``." While "``S.true is True``" is ``False``, "``S.true == True``" is ``True``, so if there is any doubt over whether a function or expression will return ``S.true`` or ``True``, just use ``==`` instead of ``is`` to do the comparison, and it will work in either case. Finally, for boolean flags, it's better to just use ``if x`` instead of ``if x is True``. To quote PEP 8: Do not compare boolean values to ``True`` or ``False`` using ``==``. * Yes: ``if greeting:`` * No: ``if greeting == True:`` * Worse: ``if greeting is True:`` Examples ======== >>> from sympy import sympify, true, false, Or >>> sympify(True) True >>> _ is True, _ is true (False, True) >>> Or(true, false) True >>> _ is true True Python operators give a boolean result for true but a bitwise result for True >>> ~true, ~True # doctest: +SKIP (False, -2) >>> true >> true, True >> True (True, 0) See Also ======== sympy.logic.boolalg.BooleanFalse c��dS�NTr,r<s r(�__bool__zBooleanTrue.__bool__Qs���tr*c� �td��Sr���hashr<s r(�__hash__zBooleanTrue.__hash__Ts���D�z�z�r*c�^��|durdS|durdSt���|��S�NTF��super�__eq__�r3r-� __class__s �r(r�zBooleanTrue.__eq__Ws5��� �D�=�=��4� �E�>�>��5��w�w�~�~�e�$�$�$r*c��tSr/)r!r<s r(�negatedzBooleanTrue.negated^s��� r*c��tjS)z� Rewrite logic operators and relationals in terms of real sets. Examples ======== >>> from sympy import true >>> true.as_set() UniversalSet )rrar<s r(rfzBooleanTrue.as_setbs ���~�r*� r�r�r�r�r�r�r�r�r�rf� __classcell__�r�s@r(r�r��s��������R�R�f������%�%�%�%�%�����X�� � � � � � � r*r�)� metaclassc�J��eZdZdZd�Zd�Z�fd�Zed���Zd�Z �xZ S)� BooleanFalsea SymPy version of ``False``, a singleton that can be accessed via ``S.false``. This is the SymPy version of ``False``, for use in the logic module. The primary advantage of using ``false`` instead of ``False`` is that shorthand Boolean operations like ``~`` and ``>>`` will work as expected on this class, whereas with ``False`` they act bitwise on 0. Functions in the logic module will return this class when they evaluate to false. Notes ====== See the notes section in :py:class:`sympy.logic.boolalg.BooleanTrue` Examples ======== >>> from sympy import sympify, true, false, Or >>> sympify(False) False >>> _ is False, _ is false (False, True) >>> Or(true, false) True >>> _ is true True Python operators give a boolean result for false but a bitwise result for False >>> ~false, ~False # doctest: +SKIP (True, -1) >>> false >> false, False >> False (True, 0) See Also ======== sympy.logic.boolalg.BooleanTrue c��dS�NFr,r<s r(r�zBooleanFalse.__bool__�s���ur*c� �td��Sr�r�r<s r(r�zBooleanFalse.__hash__�s���E�{�{�r*c�^��|durdS|durdSt���|��Sr�r�r�s �r(r�zBooleanFalse.__eq__�s5��� �D�=�=��5� �E�>�>��4��w�w�~�~�e�$�$�$r*c��tSr/)r r<s r(r�zBooleanFalse.negated�s��� r*c��tjS)z� Rewrite logic operators and relationals in terms of real sets. Examples ======== >>> from sympy import false >>> false.as_set() EmptySet )rr`r<s r(rfzBooleanFalse.as_set�s ���z�r*r�r�s@r(r�r�qs��������)�)�T������%�%�%�%�%�����X�� � � � � � � r*r�c�"�|rtntSr/)r r!�rhs r(�<lambda>r��s��1�#7�4�4�%�r*c��eZdZdZdZd�Zd�Zd�ZeZeZ eZ e d���Z dd�Z dd�Ze d ���Ze d ���Zd �Zd �Zd S)�BooleanFunctionz�Boolean function is a function that lives in a boolean space It is used as base class for :py:class:`~.And`, :py:class:`~.Or`, :py:class:`~.Not`, etc. Tc ���t|��}t|t��s |jdi���S|j�fd�|jD���}t |��S)Nc�*��g|]}|jdi�����S�r,�rT�rur�r�s �r(rwz2BooleanFunction._eval_simplify.<locals>.<listcomp>�s+���=�=�=��z�q�z�+�+�F�+�+�=�=�=r*r,)�simplify_univariater"r�rTrerz�simplify_logic)r3r��rvs ` r(r�zBooleanFunction._eval_simplify�sm��� �� &� &���"�o�.�.� )��2�;�(�(��(�(� (� �R�W�=�=�=�=�R�W�=�=�=� >���b�!�!�!r*c � �ddlm}||fi|��S)Nrr�)�sympy.simplify.simplifyrT)r3r�rTs r(rTzBooleanFunction.simplify�s,��4�4�4�4�4�4��x��'�'��'�'�'r*c�:�ttd�����r�r�r2s r(r�zBooleanFunction.__lt__�r�r*c��d�|D��S)Nc�,�g|]}t|����Sr,)r)�rurvs r(rwz=BooleanFunction.binary_check_and_simplify.<locals>.<listcomp>�s��,�,�,�!� �1� � �,�,�,r*r,)r3rzs r(�binary_check_and_simplifyz)BooleanFunction.binary_check_and_simplify�s��,�,�t�,�,�,�,r*c�&�|j|jd|i�S)NrT)�_to_nnfrzrSs r(rUzBooleanFunction.to_nnf�s���t�|�T�Y�:��:�:�:r*c�&�|j|jd|i�S�N�deep)�_to_anfrz�r3r�s r(�to_anfzBooleanFunction.to_anf�s���t�|�T�Y�2�T�2�2�2r*c�x�|�dd��}t��}|D]�}t|��s|�|��}|rRt ||��r|j}n|f}|D]3}t |��|vr |jccS|�|���4�z|�|����||�S)NrTT) �getrx� is_literalrUr"rzr;�zero�add)�clsrzr�rT�argset�argr�s r(r�zBooleanFunction._to_nnf�s����:�:�j�$�/�/������� � �C��c�?�?� +��j�j��*�*��� ��c�3�'�'�!��(�C�C��&�C��"�"�A��1�v�v��'�'�"�x�������J�J�q�M�M�M�M�"� � � �3������s�F�|�r*c���|�dd��}g}|D]S}|r:t|��rt|t��r|�|���}|�|���T||ddi�S)Nr�T�r�� remove_trueF)r�r�r"r;r��append)r�rzr�r��new_argsr�s r(r�zBooleanFunction._to_anfs����z�z�&�$�'�'����� !� !�C�� 0�!�#���0�*�S�#�*>�*>�0��*�*�$�*�/�/�C� �O�O�C� � � � ��s�H�0�%�0�0�0r*c�N�|�dd��t|g|�Ri|��S)N�evaluateT)� setdefaultr)r3�symbolsr~s r(�diffzBooleanFunction.diff s6�����z�4�0�0�0��$�8��8�8�8�K�8�8�8r*c ���||jvrLddlm}ddlm}|d||�|d��|�|d����fd��S||jvrdStjS)Nr)ro�� PiecewiserY)rYT) rtrLro�$sympy.functions.elementary.piecewiserrdr[r�Zero)r3rhrors r(�_eval_derivativez BooleanFunction._eval_derivatives��� ��#� #� #� 0� 0� 0� 0� 0� 0� F� F� F� F� F� F��9��B�B�t�y�y��A���� � �!�Q���8�8�9���� ��$�#� #� #� �D��6�Mr*Nr�)r�r�r�r�rrr�rTr�r�r�r�� classmethodr�rUr�r�r�rrr,r*r(r�r��s����������J�"�"�"�(�(�(���� �F� �F� �F��-�-��[�-�;�;�;�;�3�3�3�3�����[��&�1�1��[�1�9�9�9� � � � � r*r�c�^��eZdZdZeZeZdZe d���Z d�Z �fd�Z d�Z d�Zd d �Z�xZS) r1aS Logical AND function. It evaluates its arguments in order, returning false immediately when an argument is false and true if they are all true. Examples ======== >>> from sympy.abc import x, y >>> from sympy import And >>> x & y x & y Notes ===== The ``&`` operator is provided as a convenience, but note that its use here is different from its normal use in Python, which is bitwise and. Hence, ``And(a, b)`` and ``a & b`` will produce different results if ``a`` and ``b`` are integers. >>> And(x, y).subs(x, 1) y Nc�D�tj|�}tj|t��}g}t ��}t |��D]W}|jr9|j}||vr�|j j|vr tgcS|� |��|� |���X|Sr/) r�r�r�_new_args_filterr1rxr� is_Relationalr�r�r!r�r�)r�rz�newargs�relrh�cs r(r zAnd._new_args_filter@s����8�$�?���)�$��4�4�����e�e������ � �A��� ��K����8�8���Y�(�C�/�/�!�7�N�N�N��G�G�A�J�J�J� �N�N�1� � � � ��r*c���g}d}|jD]X} |�||��}n#t$r|�|}Y�*wxYw|dkr tcS|dkr|�|���Y|�|�||��t |t ��rPt|j��}|�|��r't|��|z }|� |��|j |�S)NFT) rzrdr%r!r�r"r1rx�issubsetr�re�r3�oldrlrz�badrv�old_sets r(� _eval_subszAnd._eval_subsRs �������� � �A� ��F�F�3��$�$����� � � ��;��C���  ���� �E�z�z�� � � ��d���� � �A����� �?� �H�H�S�#� � � � �c�3� � � ��#�(�m�m�G�����%�%� ��4�y�y�7�*������ � � ��t�y�$��� �&�7�7c �V�����ddlm�m�ddlm}t ��jdi|��}t|t��s|St|j �fd�d���\}}|s|St|�fd�d���\}}|d}|�ro|d } i�i} ttd �|D����d ���} g}g} d | v�r�| � d ��D�]D\} } | � ��}| j |ks|| jjvr�|�vr� |t!| j | j d ���|��\}}| �|| |z ��}||��| || ��zkr|} n|�| ����n#t&$rYnwxYw|�vr0|�| �|�|������| j |kr/|| jjvr!| j�|<|�| ����/| �| ����Ft+t,��}| D]V}| |D]K\}} | ����} | j}|t1|���|| f���L�W|} d | v���| D]'}|�d�| |D�����(�fd�| D��} �fd�|D��}|jd�|| z|zD��|z�}t5��}t7��}t9|||t:|���S)Nr)�EqualityrJ)� linear_coeffsc�$��t|���Sr/�r"�rvrJs �r(r�z$And._eval_simplify.<locals>.<lambda>xs���j��J�.G�.G�r*T��binaryc�$��t|���Sr/r)rvrs �r(r�z$And._eval_simplify.<locals>.<lambda>|s����A�x�)@�)@�r*�measure�ratioc� �g|] }|j|f�� Sr,)r[r�s r(rwz&And._eval_simplify.<locals>.<listcomp>�s,��#2�#2�#2�()����#�#2�#2�#2r*c�,�t|d��S�Nr)r\r�s r(r�z$And._eval_simplify.<locals>.<lambda>�s��#�a��d�)�)�r*rYF�r�c��g|]\}}|��Sr,r,)ru�fr&s r(rwz&And._eval_simplify.<locals>.<listcomp>�s��4�4�4�$�!�Q�A�4�4�4r*c�:��g|]}|������Sr,�rd�ru�eiris �r(rwz&And._eval_simplify.<locals>.<listcomp>�s#���;�;�;�2�������;�;�;r*c�:��g|]}|������Sr,r+r,s �r(rwz&And._eval_simplify.<locals>.<listcomp>�s#���3�3�3�r�R�W�W�T�]�]�3�3�3r*c��g|] }|j�� Sr,�r�r�s r(rwz&And._eval_simplify.<locals>.<listcomp>�s��K�K�K�A�A�K�K�K�Kr*)�threeterm_patternsr,)rLrrJ�sympy.solvers.solvesetrr�r�r"r1rrzrr]�lhs�rhsr[rrer�� ValueErrorrdr�list�xreplacer\�extend�_simplify_patterns_and�_simplify_patterns_and3�"_apply_patternbased_simplificationr!)r3r�rr��Rel�nonRel�eqsr-r"r#�sifted� nonlineqsrgr&rh�m�b�enew�resifted�kr)�patternsr1rrJrir�s @@@�r(r�zAnd._eval_simplifyns ������>�>�>�>�>�>�>�>�8�8�8�8�8�8� #�U�W�W� #� -� -�f� -� -���"�c�"�"� ��I��2�7�$G�$G�$G�$G�"&�(�(�(� ��V�� ��I��#�@�@�@�@��N�N�N� ��U���#�� �, W��7�O�E��D��F��'�#2�#2�-0�#2�#2�#2�3�3�#�#�%�%�F��C��I��v�+�+�%�z�z�!�}�}�,�,�G�D�!���� � �A���� � �a�1�5�+=�&=�&=�1�D�=�=� !�#0�=� #�A�E�A�E�6�E� B� B� B�A�$G�$G�D�A�q�#$�6�6�!�a�R��T�?�?�D�&�w�t�}�}��g�g�a�j�j�0@�@�@�$(��� #� � �1� � � � (�!"�� *�!�!�!� �D�!�����D�y�y�� � �1�6�6�!�T�!�W�#5�#5�6�6�6�6���!������1C�(C�(C�"#�%��Q��� � �1� � � � �"�(�(��+�+�+�+�&�t�,�,���8�8�A� &�q� �8�8���1��J�J�t�,�,���N�� ��Q���(�/�/��A��7�7�7�7�8�"��;�v�+�+�<� 6� 6��� � �4�4�&��)�4�4�4�5�5�5�5�;�;�;�;��;�;�;�I�3�3�3�3�U�3�3�3�E����K�K�#� �/�E�2I�K�K�K�f�T�V�B�)�+�+��4�6�6��1�"�h�29�5�EW�Y�Y�Y� Ys�A7F � F�Fc�6�ddlm}|d�|jD���S)Nr)� Intersectionc�6�g|]}|�����Sr,�rf�rur�s r(rwz$And._eval_as_set.<locals>.<listcomp>�s ��@�@�@�s�c�j�j�l�l�@�@�@r*)�sympy.sets.setsrHrz)r3rHs r(r_zAnd._eval_as_set�s2��0�0�0�0�0�0��|�@�@�d�i�@�@�@�A�Ar*c�2�td�|jD���S)Nc�,�g|]}t|����Sr,r:rKs r(rwz,And._eval_rewrite_as_Nor.<locals>.<listcomp>�s��3�3�3�#�S��X�X�3�3�3r*)�Norrz�r3rzr�s r(�_eval_rewrite_as_NorzAnd._eval_rewrite_as_Nor�s���3�3���3�3�3�4�4r*Tc�T�|r%tj|jd|i�}t|��S|Sr�)r1r�rz�distribute_xor_over_and)r3r��results r(r�z And.to_anf�s3�� � 3��[�$�)�7�$�7�7�F�*�6�2�2� 2�� r*r�)r�r�r�r�r!r�r �identity�nargsr r rr�r_rQr�r�r�s@r(r1r1 s����������4 �D��H� �E�����[��" � � �8BY�BY�BY�BY�BY�HB�B�B�5�5�5��������r*r1c�Z��eZdZdZeZeZed���Z d�Z d�Z d�Z �fd�Z d d�Z�xZS) r7aM Logical OR function It evaluates its arguments in order, returning true immediately when an argument is true, and false if they are all false. Examples ======== >>> from sympy.abc import x, y >>> from sympy import Or >>> x | y x | y Notes ===== The ``|`` operator is provided as a convenience, but note that its use here is different from its normal use in Python, which is bitwise or. Hence, ``Or(a, b)`` and ``a | b`` will return different things if ``a`` and ``b`` are integers. >>> Or(x, y).subs(x, 0) y c�B��g}g}tj|�}|D]p}|jrR|j}||vr�|jj�t �fd�|D����r t gcS|�|��|�|���qtj |t��S)Nc3�$�K�|] }|�kV�� dSr/r,)rurj�ncs �r(� <genexpr>z&Or._new_args_filter.<locals>.<genexpr>�s'�����,�,�1�q�B�w�,�,�,�,�,�,r*) r�r�r r�r��anyr r�rr r7)r�rzrrrhrrZs @r(r zOr._new_args_filter�s���������8�$�?��� � �A��� ��K����8�8���Y�(���,�,�,�,��,�,�,�,�,�"� �6�M�M�M�� � �1� � � � �N�N�1� � � � ��)�'�2�6�6�6r*c���g}d}|jD]X} |�||��}n#t$r|�|}Y�*wxYw|dkr tcS|dkr|�|���Y|�|�||��t |t ��rPt|j��}|�|��r't|��|z }|� |��|j |�Sr�) rzrdr%r r�r"r7rxrr�rers r(rz Or._eval_subs�s �������� � �A� ��F�F�3��$�$����� � � ��;��C���  ���� �D�y�y�� � � ��e���� � �A����� �?� �H�H�S�#� � � � �c�2� � � ��#�(�m�m�G�����%�%� ��4�y�y�7�*������ � � ��t�y�$��rc�6�ddlm}|d�|jD���S)Nr)�Unionc�6�g|]}|�����Sr,rJrKs r(rwz#Or._eval_as_set.<locals>.<listcomp> s ��9�9�9��s�z�z�|�|�9�9�9r*)rLr_rz)r3r_s r(r_zOr._eval_as_set s2��)�)�)�)�)�)��u�9�9�t�y�9�9�9�:�:r*c�2�td�|jD���S)Nc�,�g|]}t|����Sr,r:rKs r(rwz,Or._eval_rewrite_as_Nand.<locals>.<listcomp>s��4�4�4�3�c�#�h�h�4�4�4r*)�NandrzrPs r(�_eval_rewrite_as_NandzOr._eval_rewrite_as_Nands���4�4�$�)�4�4�4�5�5r*c �`����ddlm}m}m���||��}|r/��fd�|D��}��|��jdi|��St��jdi|��}t|t��s|St��}t|||dt��S)Nr)�Le�Geroc �p��i|]2}|���|j|j��|j����3Sr,)rer3r4�strict)rurvror3s ��r(� <dictcomp>z%Or._eval_simplify.<locals>.<dictcomp>sP���;�;�;�01��t�y�y���1�5�!�%� � �!�(�,�,�;�;�;r*r"r,) rLrfrgrorOr7r�r�r"r7�_simplify_patterns_orr;r ) r3r�rfrg�legerir�rFror�s ` @�r(r�zOr._eval_simplifys������4�4�4�4�4�4�4�4�4�4��z�z�"�b�!�!�� � @�;�;�;�;�;�59�;�;�;�D�5�4�=�=��&�&�5�?�?��?�?� ?� #�U�W�W� #� -� -�f� -� -���"�b�!�!� ��I�(�*�*��1�"�h�28��2C�T�K�K� Kr*Tc�����tdt�j��dz��}�fd�|D��}tj|��}d�|D��}�fd�|D��}t t |��ddi�S)NrYc3�B�K�|]}t�j|��V��dSr/)rrz)ru�jr3s �r(r[zOr.to_anf.<locals>.<genexpr>#s/�����9�9�q� �T�Y��*�*�9�9�9�9�9�9r*c3�(K�|] }t|�V��dSr/r0rKs r(r[zOr.to_anf.<locals>.<genexpr>%s&����*�*�c��S� �*�*�*�*�*�*r*c3�B�K�|]}�rt|����n|V��dS)r�N)r�)rurhr�s �r(r[zOr.to_anf.<locals>.<genexpr>&s:�����B�B���3��q�t�$�$�$�$�!�B�B�B�B�B�Br*r�F)�ranger\rzr� from_iterablerEr6)r3r�rzs`` r(r�z Or.to_anf!s������Q��D�I����*�+�+��9�9�9�9�D�9�9�9���"�4�(�(��*�*�T�*�*�*��B�B�B�B�T�B�B�B���D��J�J�2�E�2�2�2r*r�)r�r�r�r�r r�r!rUr r rr_rdr�r�r�r�s@r(r7r7�s����������4 �D��H��7�7��[�7�  � � �8;�;�;�6�6�6� K� K� K� K� K�3�3�3�3�3�3�3�3r*r7c�B�eZdZdZdZed���Zd�Zdd�Zdd�Z dS) r;a� Logical Not function (negation) Returns ``true`` if the statement is ``false`` or ``False``. Returns ``false`` if the statement is ``true`` or ``True``. Examples ======== >>> from sympy import Not, And, Or >>> from sympy.abc import x, A, B >>> Not(True) False >>> Not(False) True >>> Not(And(True, False)) True >>> Not(Or(True, False)) False >>> Not(And(And(True, x), Or(x, False))) ~x >>> ~x ~x >>> Not(And(Or(A, B), Or(~A, ~B))) ~((A | B) & (~A | ~B)) Notes ===== - The ``~`` operator is provided as a convenience, but note that its use here is different from its normal use in Python, which is bitwise not. In particular, ``~a`` and ``Not(a)`` will be different if ``a`` is an integer. Furthermore, since bools in Python subclass from ``int``, ``~True`` is the same as ``~1`` which is ``-2``, which has a boolean value of True. To avoid this issue, use the SymPy boolean types ``true`` and ``false``. - As of Python 3.12, the bitwise not operator ``~`` used on a Python ``bool`` is deprecated and will emit a warning. >>> from sympy import true >>> ~True # doctest: +SKIP -2 >>> ~true False Tc��t|t��s|dvr|rtntS|jr |jdS|jr|jSdS)N�TFr)r"rr!r �is_Notrzr r�)r�r�s r(�evalzNot.eval^s`�� �c�6� "� "� *�c�]�&:�&:��)�5�5�T� )� �:� ��8�A�;� � � � ��;� � � r*c�z�|jd����tj��S)z� Rewrite logic operators and relationals in terms of real sets. Examples ======== >>> from sympy import Not, Symbol >>> x = Symbol('x') >>> Not(x > 0).as_set() Interval(-oo, 0) r)rzrf� complementrrbr<s r(r_zNot._eval_as_seths,���y��|�"�"�$�$�/�/���8�8�8r*c ��� �t|��r|S|jd}|j|j}}|tkrt jd�|D��d|i�S|tkrtjd�|D��d|i�S|t kr/|\}}t�|t|��|���S|tkr5t�t |�t d�|D���|���S|tkrtg}tdt|��dzd��D]?}t||��D],� � fd �|D��} |� t | ����-�@tj|d|i�S|tkrf|\}}} t�t |t| ����t t|��t|����|���Std |z���) Nrc�,�g|]}t|����Sr,r:rKs r(rwzNot.to_nnf.<locals>.<listcomp>s��9�9�9�S��C���9�9�9r*rTc�,�g|]}t|����Sr,r:rKs r(rwzNot.to_nnf.<locals>.<listcomp>�s�� :� :� :�c��S��� :� :� :r*r�c�,�g|]}t|����Sr,r:rKs r(rwzNot.to_nnf.<locals>.<listcomp>�s��.H�.H�.H�C�s�3�x�x�.H�.H�.Hr*rY�c�:��g|]}|�vrt|��n|��Sr,r:�rurk�negs �r(rwzNot.to_nnf.<locals>.<listcomp>�s+���F�F�F�A��S���c�!�f�f�f�a�F�F�Fr*z!Illegal operator %s in expression)r�rzrer1r7r�r@r;rPrErrr\rr��ITEr5) r3rT�exprrerzr�rBrTrv�clauserr�s @r(rUz Not.to_nnfvs���� �d� � � ��K��y��|���Y�� �d�� �3�;�;��:�9�9�D�9�9�9�M�H�M�M� M� �2�:�:��;� :� :�T� :� :� :�N�X�N�N� N� �7�?�?��D�A�q��;�;�q�#�a�&�&�8�;�<�<� <� �:� � ��;�;�r�4�y�"�.H�.H�4�.H�.H�.H�*I�(0��2�2� 2� �3�;�;��F��1�c�$�i�i��k�1�-�-� /� /��'��a�0�0�/�/�C�F�F�F�F��F�F�F�F��M�M�"�f�+�.�.�.�.�/��;��:��:�:� :� �3�;�;��G�A�q�!��;�;�r�!�S��V�V�}�}�b��Q����Q���.@�.@�8�;�T�T� T��<�t�C�D�D�Dr*c�\�t�t|jd|���S)Nrr�)rEr�r rzr�s r(r�z Not.to_anf�s ���{�{�4���1��D�{�9�9�9r*Nr�) r�r�r�r�rwr rxr_rUr�r,r*r(r;r;*s{������/�/�b�F�����[�� 9� 9� 9�"E�"E�"E�"E�H:�:�:�:�:�:r*r;c�n��eZdZdZdd��fd� Zeed�����Zd d�Zd�Z d�Z d �Z d �Z �xZ S) rEac Logical XOR (exclusive OR) function. Returns True if an odd number of the arguments are True and the rest are False. Returns False if an even number of the arguments are True and the rest are False. Examples ======== >>> from sympy.logic.boolalg import Xor >>> from sympy import symbols >>> x, y = symbols('x y') >>> Xor(True, False) True >>> Xor(True, True) False >>> Xor(True, False, True, True, False) True >>> Xor(True, False, True, False) False >>> x ^ y x ^ y Notes ===== The ``^`` operator is provided as a convenience, but note that its use here is different from its normal use in Python, which is bitwise xor. In particular, ``a ^ b`` and ``Xor(a, b)`` will be different if ``a`` and ``b`` are integers. >>> Xor(x, y).subs(y, 0) x T)r�c����t��}t��j|g|�Ri|��}|jD]�}t |t ��s|dvr |rt }n�&t |t��r9|jD]0}||vr|� |��n|� |���1�t||vr|� |����|� |����d�|D��}d} g} t|��D]j\} \} } }t| dzt|����D](}||dd�\}}||kr| } n || krn�)�S| �| |f���k| r=t |vr|� t ��n|� t ��| D]/\}}|� |��|� |���0t|��dkrtSt|��dkr|���Sd|vr-|r+|� d��t#t|���St%t'|����|_t)|��|_|S)Nrvc�D�g|]}|j� ||j|jjf��Sr,)r r�r�)rurjs r(rwzXor.__new__.<locals>.<listcomp>�s<��3�3�3��!�/�3��1�;�� � 3�4�3�3�3r*FrYrrT)rxr��__new__�_argsr"rr rErz�remover�� enumeraterrr\r�r!r]r;�tupler� frozenset�_argset)r�r�rzr�r��objr�r�r�oddr�rvrjrrZro�rj�cjrBr�s �r(r�z Xor.__new__�s���������e�g�g�o�c�3�D�3�3�3�F�3�3���9� � �C��#�v�&�&� �#��*>�*>����C�C���#�s�#�#� ���G�G�A�()�V� � �F�M�M�!�$�$�$����A�����G������ � �c�"�"�"�"�� � �3�����3�3��3�3�3������&�s�^�^� #� #�M�A�z��1�b��1�q�5�#�c�(�(�+�+� � ���Q��������B���8�8�!�'�C��E��1�W�W��E��� �M�M�1�b�'� "� "� "� "� � H�#'�6�>�>�F�M�M�$� � � �v�z�z�$�7G�7G��� � �D�A�q� �M�M�!� � � � �M�M�!� � � � � �v�;�;�!� � ��L� ��[�[�A� � ��:�:�<�<� � �V�^�^� �^� �M�M�$� � � ��s�F�|�$�$� $��g�f�o�o�.�.�C�I�#�F�+�+�C�K��Jr*c�D�tt|j����Sr/�r�rr�r<s r(rzzXor.args�����W�T�\�*�*�+�+�+r*c� ��g}tdt|j��dzd��D]I}t|j|��D]1��fd�|jD��}|�t |����2�Jt j|d|i�S)NrrYrc�:��g|]}|�vrt|��n|��Sr,r:r�s �r(rwzXor.to_nnf.<locals>.<listcomp>s+���G�G�G��A��H�H�#�a�&�&�&�!�G�G�Gr*rT)rrr\rzrr�r7r1r�)r3rTrzrvr�r�s @r(rUz Xor.to_nnf�s�������q�#�d�i�.�.��*�A�.�.� )� )�A�#�D�I�q�1�1� )� )��G�G�G�G�T�Y�G�G�G��� � �B��K�(�(�(�(� )��{�D�4�8�4�4�4r*c�p���j}t�fd�tt|����D���S)Nc�:��g|]}t|�j����Sr,)�_convert_to_varsSOPrz�rurhr3s �r(rwz+Xor._eval_rewrite_as_Or.<locals>.<listcomp>s5���<�<�<��(��4�9�5�5�<�<�<r*)rzr7�_get_odd_parity_termsr\�r3rzr�r�s` r(�_eval_rewrite_as_OrzXor._eval_rewrite_as_OrsK��� �I���<�<�<�<�2�3�q�6�6�:�:�<�<�<�=� =r*c�p���j}t�fd�tt|����D���S)Nc�:��g|]}t|�j����Sr,)�_convert_to_varsPOSrzr�s �r(rwz,Xor._eval_rewrite_as_And.<locals>.<listcomp> s5���>�>�>��)��D�I�6�6�>�>�>r*)rzr1�_get_even_parity_termsr\r�s` r(�_eval_rewrite_as_AndzXor._eval_rewrite_as_And sK��� �I���>�>�>�>�4�S��V�V�<�<�>�>�>�?� ?r*c ����|j�fd�|jD���}|���}t|t��s|St ��}t ||�dd��S)Nc�*��g|]}|jdi�����Sr�r�r�s �r(rwz&Xor._eval_simplify.<locals>.<listcomp>s+���A�A�A�!����-�-�f�-�-�A�A�Ar*r")rerzr�r"rE�_simplify_patterns_xorr;)r3r�r�rFs ` r(r�zXor._eval_simplifys|����T�Y�A�A�A�A�t�y�A�A�A� B�� �Y�Y�[�[���"�c�"�"� ��I�)�+�+��1�"�h�28��2C�T�K�K� Kr*c���t|t��rdt|j��}|�|j��r8t|j��|z }|�|��|j|�SdSdSr/)r"rErxrzrr�re)r3rrlrrzs r(rzXor._eval_subss�� �c�3� � � (��#�(�m�m�G����� �*�*� (��4�9�~�~��/������ � � � �t�y�$�'�'�  (� (� (� (r*r�)r�r�r�r�r�r�r rzrUr�r�r�rr�r�s@r(rErE�s��������&�&�N)-�.�.�.�.�.�.�.�d� �,�,� �W��X�,�5�5�5�5�=�=�=� ?�?�?� K� K� K�(�(�(�(�(�(�(r*rEc�(�eZdZdZed���ZdS)rca� Logical NAND function. It evaluates its arguments in order, giving True immediately if any of them are False, and False if they are all True. Returns True if any of the arguments are False Returns False if all arguments are True Examples ======== >>> from sympy.logic.boolalg import Nand >>> from sympy import symbols >>> x, y = symbols('x y') >>> Nand(False, True) True >>> Nand(True, True) False >>> Nand(x, y) ~(x & y) c�.�tt|���Sr/)r;r1�r�rzs r(rxz Nand.eval>����3��:���r*N�r�r�r�r�r rxr,r*r(rcrc&s9��������.����[���r*rcc�(�eZdZdZed���ZdS)rOa* Logical NOR function. It evaluates its arguments in order, giving False immediately if any of them are True, and True if they are all False. Returns False if any argument is True Returns True if all arguments are False Examples ======== >>> from sympy.logic.boolalg import Nor >>> from sympy import symbols >>> x, y = symbols('x y') >>> Nor(True, False) False >>> Nor(True, True) False >>> Nor(False, True) False >>> Nor(False, False) True >>> Nor(x, y) ~(x | y) c�.�tt|���Sr/)r;r7r�s r(rxzNor.eval`s���2�t�9�~�~�r*Nr�r,r*r(rOrOCs9��������8����[���r*rOc�(�eZdZdZed���ZdS)�Xnora  Logical XNOR function. Returns False if an odd number of the arguments are True and the rest are False. Returns True if an even number of the arguments are True and the rest are False. Examples ======== >>> from sympy.logic.boolalg import Xnor >>> from sympy import symbols >>> x, y = symbols('x y') >>> Xnor(True, False) False >>> Xnor(True, True) True >>> Xnor(True, False, True, True, False) False >>> Xnor(True, False, True, False) True c�.�tt|���Sr/)r;rEr�s r(rxz Xnor.evalr�r*Nr�r,r*r(r�r�es9��������2����[���r*r�c�8�eZdZdZed���Zdd�Zdd�ZdS)r@a  Logical implication. A implies B is equivalent to if A then B. Mathematically, it is written as `A \Rightarrow B` and is equivalent to `\neg A \vee B` or ``~A | B``. Accepts two Boolean arguments; A and B. Returns False if A is True and B is False Returns True otherwise. Examples ======== >>> from sympy.logic.boolalg import Implies >>> from sympy import symbols >>> x, y = symbols('x y') >>> Implies(True, False) False >>> Implies(False, False) True >>> Implies(True, True) True >>> Implies(False, True) True >>> x >> y Implies(x, y) >>> y << x Implies(x, y) Notes ===== The ``>>`` and ``<<`` operators are provided as a convenience, but note that their use here is different from their normal use in Python, which is bit shifts. Hence, ``Implies(a, b)`` and ``a >> b`` will return different things if ``a`` and ``b`` are integers. In particular, since Python considers ``True`` and ``False`` to be integers, ``True >> True`` will be the same as ``1 >> 1``, i.e., 0, which has a truth value of False. To avoid this issue, use the SymPy objects ``true`` and ``false``. >>> from sympy import true, false >>> True >> False 1 >>> true >> false False c�<� g}|D]S}t|t��s|dvr#|�t|�����>|�|���T|\}}n<#t$r/t dt |��t |��fz���wxYw|dvs|dvrtt|��|��S||krtS|j r7|j r0|j |j krtS|j j |j kr|SdStj|g|�R�S)N�rrYz:%d operand(s) used for an Implies (pairs are required): %srv)r"rr��boolr5r\�strr7r;r r r�r�r r�)r�rzrrh�A�Bs r(rxz Implies.eval�s]�� E��G�� &� &���a��(�(�&�A��K�K��N�N�4��7�7�+�+�+�+��N�N�1�%�%�%�%��D�A�q�q��� E� E� E��+�.1�$�i�i��T���-C�D�E�E� E� E���� � � � ��m�!3�!3��c�!�f�f�a�=�=� � �!�V�V��K� �_� -��� -��{�a�k�)�)�� ��y�"�a�k�1�1���2�1��=��,�t�,�,�,� ,s �AA � 9BTc�j�|j\}}t�t|��||���S�Nr�)rzr7r�r;)r3rTr�rBs r(rUzImplies.to_nnf�s+���y���1��z�z�#�a�&�&�!�h�z�7�7�7r*c�x�|j\}}t�t|t ||��|���S)Nr�)rzrEr�r r1�r3r�r�rBs r(r�zImplies.to_anf�s/���y���1��{�{�4��C��1�I�I�D�{�9�9�9r*Nr�)r�r�r�r�r rxrUr�r,r*r(r@r@�sb������/�/�`�-�-��[�-�28�8�8�8�:�:�:�:�:�:r*r@c�X��eZdZdZ�fd�Zeed�����Zdd�Zdd�Z �xZ S)rPa Equivalence relation. ``Equivalent(A, B)`` is True iff A and B are both True or both False. Returns True if all of the arguments are logically equivalent. Returns False otherwise. For two arguments, this is equivalent to :py:class:`~.Xnor`. Examples ======== >>> from sympy.logic.boolalg import Equivalent, And >>> from sympy.abc import x >>> Equivalent(False, False, False) True >>> Equivalent(True, False, False) False >>> Equivalent(x, And(x, True)) True c�@��ddlm}d�|D��}t|��}|D]R}t|t��s|dvr7|�|��|�t|�����Sg}|D]9}t||��r'|�||j |j j f���:g}t|��D]o\} \}} } t| dzt|����D]E} || dd�\} }|| kr tccS|| kr|�|| f��n�F�p|D]D\}}|�|��|�|��|�d���Et|��dkrt Sd|vr|�d��t#|�Sd|vr(|�d��t#d �|D���St%|��}t'���||��}||_|S) NrrIc�,�g|]}t|����Sr,)rrKs r(rwz&Equivalent.__new__.<locals>.<listcomp>�s��.�.�.�#��� � �.�.�.r*rvrYrTFc�,�g|]}t|����Sr,r:rKs r(rwz&Equivalent.__new__.<locals>.<listcomp>s��4�4�4�c��S���4�4�4r*)rLrJrxr"r�discardr�r�r�r�r�r�rrr\r!r�r r1r�r�r�r�)r�rz�optionsrJr�rhrrjr�rvrrZror�r�r�rBr�r�r�s �r(r�zEquivalent.__new__�s]���4�4�4�4�4�4�.�.��.�.�.���T����� $� $�A��!�V�$�$� $��]�(:�(:����q�!�!�!�� � �4��7�7�#�#�#����� B� B�A��!�Z�(�(� B�� � �A�q�{�A�I�,?�@�A�A�A����&�s�^�^� � �M�A�z��1�b��1�q�5�#�c�(�(�+�+� � ���Q��������B���8�8� �L�L�L�L�L��1�W�W��M�M�1�b�'�*�*�*��E���� � �D�A�q� �M�M�!� � � � �M�M�!� � � � �J�J�t� � � � � �v�;�;�!� � ��K� �6�>�>� �N�N�4� � � ���<� � �F�?�?� �N�N�5� !� !� !��4�4�V�4�4�4�5� 5��&�!�!���g�g�o�o�c�5�)�)���� �� r*c�D�tt|j����Sr/r�r<s r(rzzEquivalent.argsr�r*Tc�d�g}t|j|jdd���D]5\}}|�tt |��|�����6|�tt |jd��|jd����t j|d|i�S)NrY�����rrT)�ziprzr�r7r;r1r�)r3rTrzr�rBs r(rUzEquivalent.to_nnfs������� �4�9�Q�R�R�=�1�1� '� '�D�A�q� �K�K��3�q�6�6�1� � � &� &� &� &� � � �B�s�4�9�R�=�)�)�4�9�Q�<�8�8�9�9�9��{�D�4�8�4�4�4r*c��t|j�}td�|jD���}t|��}t�|||���S)Nc�J�g|] }tt|��d�����!S)Fr�)r�r;rKs r(rwz%Equivalent.to_anf.<locals>.<listcomp>'s+��D�D�D�3�&��S����.�.�.�D�D�Dr*r�)r1rzrSrEr�r�s r(r�zEquivalent.to_anf%sM�� ���O�� �D�D�$�)�D�D�D� E�� #�A� &� &���{�{�1�a�d�{�+�+�+r*r�) r�r�r�r�r�r�r rzrUr�r�r�s@r(rPrP�s����������.%�%�%�%�%�R� �,�,� �W��X�,�5�5�5�5�,�,�,�,�,�,�,�,r*rPc�B�eZdZdZd�Zed���Zd d�Zd�Zd�Z dS) r�aC If-then-else clause. ``ITE(A, B, C)`` evaluates and returns the result of B if A is true else it returns the result of C. All args must be Booleans. From a logic gate perspective, ITE corresponds to a 2-to-1 multiplexer, where A is the select signal. Examples ======== >>> from sympy.logic.boolalg import ITE, And, Xor, Or >>> from sympy.abc import x, y, z >>> ITE(True, False, True) False >>> ITE(Or(True, False), And(True, True), Xor(True, True)) True >>> ITE(x, y, z) ITE(x, y, z) >>> ITE(True, x, y) x >>> ITE(False, x, y) y >>> ITE(x, y, y) y Trying to use non-Boolean args will generate a TypeError: >>> ITE(True, [], ()) Traceback (most recent call last): ... TypeError: expecting bool, Boolean or ITE, not `[]` c�h�ddlm}m}t|��dkrt d���|\}}}t |||f��r�t t||f��\}}t��j d�||fD���}tt|j ��|z ��dkr�|} |j tur|j }nc|j tur|j }nM|j turt|j ��}n*|j turt|j ��}nt}t | |��rt|��}n t �|||��\}}}d} |�dd��r|�|||��} | �t �||||d � ��} | S) Nrrn�zexpecting exactly 3 argsc��g|] }|j�� Sr,)rtr�s r(rwzITE.__new__.<locals>.<listcomp>[s��$F�$F�$F�!�Q�%5�$F�$F�$Fr*rYr�TFr')rLrorpr\r5r"�mapr)rxryrzr3r r4r!r;r�r�r�rxr�) r�rzr�rorpr�rBr�bin_syms�_ar�s r(r�z ITE.__new__Ps���0�0�0�0�0�0�0�0� �t�9�9��>�>��7�8�8� 8����1�a� �a�"�b�� "� "� ��z�A�q�6�*�*�D�A�q�"�s�u�u�{�$F�$F��1�v�$F�$F�$F�G�H��3�q�v�;�;��)�*�*�a�/�/����5�D�=�=���A�A��U�d�]�]���A�A��U�e�^�^��A�E� � �A�A��U�e�^�^��A�E� � �A�A��A��b�"�%�%���A���A��%�?�?��1�a���G�A�q�!� �� �:�:�j�$� '� '� #����!�Q��"�"�B� �:� �(�(��a��A��(�F�F�B�� r*c�F�ddlm}m}|\}}}t|||f��r�|}t|jvr|jtur|jn|j}nGt|jvr7|jturt|j��nt|j��}nd}|�t||��rt|��}|tur|S|tur|S||kr|S|tur |tur|S|tur|turt|��S|||g|kr||||d���SdS)NrrnFr') rLrorpr"r rzr4r3r!r;)r�rzrorpr�rBrr�s r(rxzITE.evalvsG��0�0�0�0�0�0�0�0����1�a� �a�"�b�� "� "� ��B��q�v�~�~��U�d�]�]�A�E�E������!�&���"#�%�5�.�.�C���J�J�J�c�!�%�j�j������~�*�R��"4�"4�~���F�F�� ��9�9��H� ��:�:��H� ��6�6��H��D�y�y�Q�%�Z�Z����E�z�z�a�4�i�i��1�v�v� � �q�!�9�� � ��3�q�!�Q��/�/�/� /� � r*Tc��|j\}}}t�tt |��|��t||��|���Sr�)rzr1r�r7r;)r3rTr�rBrs r(rUz ITE.to_nnf�s=���)���1�a��{�{�2�c�!�f�f�a�=�=�"�Q��(�(�X�{�F�F�Fr*c�N�|������Sr/)rUrfr<s r(r_zITE._eval_as_set�s���{�{�}�}�#�#�%�%�%r*c�R�ddlm}||d|df|ddf��S)NrrrYrT)rr)r3rzr�rs r(�_eval_rewrite_as_PiecewisezITE._eval_rewrite_as_Piecewise�s;��B�B�B�B�B�B��y�$�q�'�4��7�+�d�1�g�t�_�=�=�=r*Nr�) r�r�r�r�r�r rxrUr_r�r,r*r(r�r�,s�������"�"�F$�$�$�L�0�0��[�0�<G�G�G�G�&�&�&�>�>�>�>�>r*r�c�(�eZdZdZed���ZdS)� Exclusivea� True if only one or no argument is true. ``Exclusive(A, B, C)`` is equivalent to ``~(A & B) & ~(A & C) & ~(B & C)``. For two arguments, this is equivalent to :py:class:`~.Xor`. Examples ======== >>> from sympy.logic.boolalg import Exclusive >>> Exclusive(False, False, False) True >>> Exclusive(False, True, False) True >>> Exclusive(False, True, True) False c ��g}t|d��D]5\}}|�tt||�������6t|�S)Nr)rr�r;r1)r�rz�and_argsr�rBs r(rxzExclusive.eval�sQ���� ��q�)�)� ,� ,�D�A�q� �O�O�C��A�q� � �N�N� +� +� +� +��H�~�r*Nr�r,r*r(r�r��s9��������&����[���r*r�c�6�t�|��S)aReturn a list of the conjuncts in ``expr``. Examples ======== >>> from sympy.logic.boolalg import conjuncts >>> from sympy.abc import A, B >>> conjuncts(A & B) frozenset({A, B}) >>> conjuncts(A | B) frozenset({A | B}) )r1� make_args�r�s r(� conjunctsr��s�� �=�=�� � �r*c�6�t�|��S)aReturn a list of the disjuncts in ``expr``. Examples ======== >>> from sympy.logic.boolalg import disjuncts >>> from sympy.abc import A, B >>> disjuncts(A | B) frozenset({A, B}) >>> disjuncts(A & B) frozenset({A & B}) �r7r�r�s r(� disjunctsr��s�� �<�<�� � �r*c�:�t|ttf��S)ai Given a sentence ``expr`` consisting of conjunctions and disjunctions of literals, return an equivalent sentence in CNF. Examples ======== >>> from sympy.logic.boolalg import distribute_and_over_or, And, Or, Not >>> from sympy.abc import A, B, C >>> distribute_and_over_or(Or(A, And(Not(B), Not(C)))) (A | ~B) & (A | ~C) )� _distributer1r7r�s r(�distribute_and_over_orr��s�� ��c�2�� '� '�'r*c�:�t|ttf��S)a� Given a sentence ``expr`` consisting of conjunctions and disjunctions of literals, return an equivalent sentence in DNF. Note that the output is NOT simplified. Examples ======== >>> from sympy.logic.boolalg import distribute_or_over_and, And, Or, Not >>> from sympy.abc import A, B, C >>> distribute_or_over_and(And(Or(Not(A), B), C)) (B & C) | (C & ~A) )r�r7r1r�s r(�distribute_or_over_andr��s�� ��b�#�� '� '�'r*c�:�t|ttf��S)a� Given a sentence ``expr`` consisting of conjunction and exclusive disjunctions of literals, return an equivalent exclusive disjunction. Note that the output is NOT simplified. Examples ======== >>> from sympy.logic.boolalg import distribute_xor_over_and, And, Xor, Not >>> from sympy.abc import A, B, C >>> distribute_xor_over_and(And(Xor(Not(A), B), C)) (B & C) ^ (C & ~A) )r�rEr1r�s r(rSrSs�� ��c�3�'� (� (�(r*c �:����t�d�d��r��djD]}t|�d��r|�n ��dS�d�fd��djD�����dttt��fd��jD������ddi�St�d�d��rE�dttt�fd��djD������ddi�S�dS) zO Distributes ``info[1]`` over ``info[2]`` with respect to ``info[0]``. rrrYc���g|]}|�u�|�� Sr,r,)rur��conjs �r(rwz_distribute.<locals>.<listcomp>$s���B�B�B�q�A�T�M�M��M�M�Mr*c�R��g|]#}�d|����d�df��$S�rrYr,)rur�info�rests ��r(rwz_distribute.<locals>.<listcomp>&sH���"6�"6�"6�&'�$+�4��7�1�d�#3�#3�T�!�W�d�1�g�"F�"6�"6�"6r*r�Fc�2��g|]}|�d�df��S)rYrr,)rurhr�s �r(rwz_distribute.<locals>.<listcomp>*s8���"9�"9�"9�&'�$%�d�1�g�t�A�w�"7�"9�"9�"9r*)r"rzr6r�r�)r�r�r�r�s` @@r(r�r�s�������$�q�'�4��7�#�#����7�<� � �C��#�t�A�w�'�'� ����� ���7�N��t�A�w�B�B�B�B�D��G�L�B�B�B�C���t�A�w��S��"6�"6�"6�"6�"6�+/�9�"6�"6�"6�7�7�8�8�L�EJ�L�L� L� �D��G�T�!�W� %� %���t�A�w��S��"9�"9�"9�"9�+/��7�<�"9�"9�"9�:�:�;�;�*�$)�*�*� *� �A�w�r*Tc�n�t|��}t|��r|S|�|���S)a\ Converts expr to Algebraic Normal Form (ANF). ANF is a canonical normal form, which means that two equivalent formulas will convert to the same ANF. A logical expression is in ANF if it has the form .. math:: 1 \oplus a \oplus b \oplus ab \oplus abc i.e. it can be: - purely true, - purely false, - conjunction of variables, - exclusive disjunction. The exclusive disjunction can only contain true, variables or conjunction of variables. No negations are permitted. If ``deep`` is ``False``, arguments of the boolean expression are considered variables, i.e. only the top-level expression is converted to ANF. Examples ======== >>> from sympy.logic.boolalg import And, Or, Not, Implies, Equivalent >>> from sympy.logic.boolalg import to_anf >>> from sympy.abc import A, B, C >>> to_anf(Not(A)) A ^ True >>> to_anf(And(Or(A, B), Not(C))) A ^ B ^ (A & B) ^ (A & C) ^ (B & C) ^ (A & B & C) >>> to_anf(Implies(Not(A), Equivalent(B, C)), deep=False) True ^ ~A ^ (~A & (Equivalent(B, C))) r�)r�is_anfr�)r�r�s r(r�r�1s7��J �4�=�=�D� �d�|�|��� � �;�;�D�;� !� !�!r*c�P�t||��r|S|�|��S)aS Converts ``expr`` to Negation Normal Form (NNF). A logical expression is in NNF if it contains only :py:class:`~.And`, :py:class:`~.Or` and :py:class:`~.Not`, and :py:class:`~.Not` is applied only to literals. If ``simplify`` is ``True``, the result contains no redundant clauses. Examples ======== >>> from sympy.abc import A, B, C, D >>> from sympy.logic.boolalg import Not, Equivalent, to_nnf >>> to_nnf(Not((~A & ~B) | (C & D))) (A | B) & (~C | ~D) >>> to_nnf(Equivalent(A >> B, B >> A)) (A | ~B | (A & ~B)) & (B | ~A | (B & ~A)) )�is_nnfrU)r�rTs r(rUrU]s-��(�d�H����� � �;�;�x� � � r*Fc�V�t|��}t|t��s|S|rQ|s<tt |����dkrt t d�����t|dd|���St|��r|St|��}t|��}|S)ao Convert a propositional logical sentence ``expr`` to conjunctive normal form: ``((A | ~B | ...) & (B | C | ...) & ...)``. If ``simplify`` is ``True``, ``expr`` is evaluated to its simplest CNF form using the Quine-McCluskey algorithm; this may take a long time. If there are more than 8 variables the ``force`` flag must be set to ``True`` to simplify (default is ``False``). Examples ======== >>> from sympy.logic.boolalg import to_cnf >>> from sympy.abc import A, B, D >>> to_cnf(~(A | B) | D) (D | ~A) & (D | ~B) >>> to_cnf((A | B) & (A | ~A), True) A | B ��� To simplify a logical expression with more than 8 variables may take a long time and requires the use of `force=True`.�cnfT��force) rr"r�r\�_find_predicatesr5rr��is_cnf�eliminate_implicationsr�)r�rTr��ress r(�to_cnfr�vs���( �4�=�=�D� �d�O� ,� ,��� ��>�� *��-�d�3�3�4�4�q�8�8��Z�)(�)�)�*�*� *��d�E�4�u�=�=�=�=��d�|�|��� � !�$� '� '�D� �� &� &�C� �Jr*c�R�t|��}t|t��s|S|rQ|s<tt |����dkrt t d�����t|dd|���St|��r|St|��}t|��S)a� Convert a propositional logical sentence ``expr`` to disjunctive normal form: ``((A & ~B & ...) | (B & C & ...) | ...)``. If ``simplify`` is ``True``, ``expr`` is evaluated to its simplest DNF form using the Quine-McCluskey algorithm; this may take a long time. If there are more than 8 variables, the ``force`` flag must be set to ``True`` to simplify (default is ``False``). Examples ======== >>> from sympy.logic.boolalg import to_dnf >>> from sympy.abc import A, B, C >>> to_dnf(B & (A | C)) (A & B) | (B & C) >>> to_dnf((A & B) | (A & ~B) | (B & C) | (~B & C), True) A | C r�r��dnfTr�) rr"r�r\r�r5rr��is_dnfr�r�)r�rTr�s r(�to_dnfr�s���( �4�=�=�D� �d�O� ,� ,��� ��>�� *��-�d�3�3�4�4�q�8�8��Z�)(�)�)�*�*� *��d�E�4�u�=�=�=�=��d�|�|��� � !�$� '� '�D� !�$� '� '�'r*c��t|��}t|��rt|t��sdSt|t��r|jD] }|jsdS� dSt|t��ra|jD]W}t|t��r|jD] }|jsdS��-t|��rt|t��rdS�UdSdSdS)a� Checks if ``expr`` is in Algebraic Normal Form (ANF). A logical expression is in ANF if it has the form .. math:: 1 \oplus a \oplus b \oplus ab \oplus abc i.e. it is purely true, purely false, conjunction of variables or exclusive disjunction. The exclusive disjunction can only contain true, variables or conjunction of variables. No negations are permitted. Examples ======== >>> from sympy.logic.boolalg import And, Not, Xor, true, is_anf >>> from sympy.abc import A, B, C >>> is_anf(true) True >>> is_anf(A) True >>> is_anf(And(A, B, C)) True >>> is_anf(Xor(A, Not(B))) False TF)rr�r"r;r1rzrsrE)r�r�r�s r(r�r��s��8 �4�=�=�D��$���� �4�� 5� 5���t��$������9� � �C��=� ��u�u� ��t� �D�#� � ���9� � �C��#�s�#�#� ���%�%�A��;�%�$�u�u�u�%�%��C��� ��c�3�'�'�!� �5�5�!��u�u��t��ur*c�B�t|��}t|��rdS|g}|ry|���}|jtt fvr=|r |j}|D]}t|��|vrdS�|�|j��nt|��sdS|�ydS)a� Checks if ``expr`` is in Negation Normal Form (NNF). A logical expression is in NNF if it contains only :py:class:`~.And`, :py:class:`~.Or` and :py:class:`~.Not`, and :py:class:`~.Not` is applied only to literals. If ``simplified`` is ``True``, checks if result contains no redundant clauses. Examples ======== >>> from sympy.abc import A, B, C >>> from sympy.logic.boolalg import Not, is_nnf >>> is_nnf(A & B | ~C) True >>> is_nnf((A | ~A) & (B | C)) False >>> is_nnf((A | ~A) & (B | C), False) True >>> is_nnf(Not(A & B) | C) False >>> is_nnf((A >> B) & (B >> A)) False TF) rr�r]rer1r7rzr;r8)r�� simplified�stackrzr�s r(r�r�s���6 �4�=�=�D��$�����t� �F�E� � ��y�y�{�{�� �9��b� � !� !�� %��y���%�%�C��3�x�x�4�'�'�$�u�u�(� �L�L��� #� #� #� #��D�!�!� ��5� � � �4r*c�8�t|tt��S)a( Test whether or not an expression is in conjunctive normal form. Examples ======== >>> from sympy.logic.boolalg import is_cnf >>> from sympy.abc import A, B, C >>> is_cnf(A | B | C) True >>> is_cnf(A & B & C) True >>> is_cnf((A & B) | C) False )�_is_formr1r7r�s r(r�r�1s��" �D�#�r� "� "�"r*c�8�t|tt��S)aM Test whether or not an expression is in disjunctive normal form. Examples ======== >>> from sympy.logic.boolalg import is_dnf >>> from sympy.abc import A, B, C >>> is_dnf(A | B | C) True >>> is_dnf(A & B & C) True >>> is_dnf((A & B) | C) True >>> is_dnf(A & (B | C)) False )rr7r1r�s r(rrEs��& �D�"�c� "� "�"r*c�L�t|��}t||��r|�|��n|g}|D]i}t||��rCt||��r|�|��n|g}|D]}t|��durdS��Ut|��durdS�jdS)zE Test whether or not an expression is of the required form. FT)rr"r�r�)r�� function1� function2�vals�lit�vals2�ls r(rr[s��� �4�=�=�D�(2�4��(C�(C� O�9� � �t� $� $� $�$��D����� �c�9� %� %� �0:�3� �0J�0J�U�I�'�'��,�,�,�QT�PU�E�� !� !���a�=�=�E�)�)� �5�5�5�*� !���_�_�� %� %��5�5�&� �4r*c�$�t|d���S)a� Change :py:class:`~.Implies` and :py:class:`~.Equivalent` into :py:class:`~.And`, :py:class:`~.Or`, and :py:class:`~.Not`. That is, return an expression that is equivalent to ``expr``, but has only ``&``, ``|``, and ``~`` as logical operators. Examples ======== >>> from sympy.logic.boolalg import Implies, Equivalent, eliminate_implications >>> from sympy.abc import A, B, C >>> eliminate_implications(Implies(A, B)) B | ~A >>> eliminate_implications(Equivalent(A, B)) (A | ~B) & (B | ~A) >>> eliminate_implications(Equivalent(A, B, C)) (A | ~C) & (B | ~A) & (C | ~B) Fr�)rUr�s r(r�r�os��, �$�� '� '� '�'r*c����ddlm�t�t��rt �jd��S�dvst����s�jrdSt�t��s#t��fd��jD����rdSdS)a{ Returns True if expr is a literal, else False. Examples ======== >>> from sympy import Or, Q >>> from sympy.abc import A, B >>> from sympy.logic.boolalg import is_literal >>> is_literal(A) True >>> is_literal(~A) True >>> is_literal(Q.zero(A)) True >>> is_literal(A + B) True >>> is_literal(Or(A, B)) False r)�AppliedPredicatervTc3�F�K�|]}t����p|jV��dSr/)r"r�)rur�rr�s ��r(r[zis_literal.<locals>.<genexpr>�sN�����7R�7R�BC�Z��.� /� /� <�1�9�7R�7R�7R�7R�7R�7Rr*F) r}rr"r;r�rzr�r��all)r�rs`@r(r�r��s�����,3�2�2�2�2�2��$������$�)�A�,�'�'�'� �� � �*�T�3C�"D�"D� �� � ��t� ��o� .� .��3�7R�7R�7R�7R�7R�GK�y�7R�7R�7R�4R�4R���t� �5r*c ����tt�tdt���dz�������d����fd�|D��S)a  Takes clauses in CNF format and puts them into an integer representation. Examples ======== >>> from sympy.logic.boolalg import to_int_repr >>> from sympy.abc import x, y >>> to_int_repr([x | y, y], [x, y]) == [{1, 2}, {2}] True rYc�d�t|t��r||jd S||Sr&)r"r;rz)r�rs r(� append_symbolz"to_int_repr.<locals>.append_symbol�s2�� �c�3� � � ��C�H�Q�K�(�(� (��3�<� r*c�^��g|])}��fd�t�|��D����*S)c�(��h|]}�|�����Sr,r,)rur�rrs ��r(� <setcomp>z)to_int_repr.<locals>.<listcomp>.<setcomp>�s%��� D� D� D�S�]�]�3�� (� (� D� D� Dr*r�)rurrrs ��r(rwzto_int_repr.<locals>.<listcomp>�sK��� � � �� E� D� D� D� D�B�L�L��O�O� D� D� D� � � r*)�dictr�rrr\)�clausesrrs `@r(� to_int_reprr�sq�����3�w��a��W����)9� :� :�;�;�<�<�G� � � �  � � � � �� � � �r*c ��td�tttt|��������d��S)a@ Return an integer corresponding to the base-2 digits given by *term*. Parameters ========== term : a string or list of ones and zeros Examples ======== >>> from sympy.logic.boolalg import term_to_integer >>> term_to_integer([1, 0, 0]) 4 >>> term_to_integer('100') 4 �r)�int�joinr6r�r�)�terms r(�term_to_integerr$�s8��( �r�w�w�t�C��T�$�Z�Z�0�0�1�1�2�2�A� 6� 6�6r*c #�fK�d�|D��}t|��}t|t��st|��sdSt dt |�����}|D]L}|�tt||������}|rt|��|fV��H|V��MdS)a� Return a generator of all possible configurations of the input variables, and the result of the boolean expression for those values. Parameters ========== expr : Boolean expression variables : list of variables input : bool (default ``True``) Indicates whether to return the input combinations. Examples ======== >>> from sympy.logic.boolalg import truth_table >>> from sympy.abc import x,y >>> table = truth_table(x >> y, [x, y]) >>> for t in table: ... print('{0} -> {1}'.format(*t)) [0, 0] -> True [0, 1] -> True [1, 0] -> False [1, 1] -> True >>> table = truth_table(x | y, [x, y]) >>> list(table) [([0, 0], False), ([0, 1], True), ([1, 0], True), ([1, 1], True)] If ``input`` is ``False``, ``truth_table`` returns only a list of truth values. In this case, the corresponding input values of variables can be deduced from the index of a given output. >>> from sympy.utilities.iterables import ibin >>> vars = [y, x] >>> values = truth_table(x >> y, vars, input=False) >>> values = list(values) >>> values [True, False, True, True] >>> for i, value in enumerate(values): ... print('{0} -> {1}'.format(list(zip( ... vars, ibin(i, len(vars)))), value)) [(y, 0), (x, 0)] -> True [(y, 0), (x, 1)] -> False [(y, 1), (x, 0)] -> True [(y, 1), (x, 1)] -> True c�,�g|]}t|����Sr,)r�ru�vs r(rwztruth_table.<locals>.<listcomp>s��/�/�/������/�/�/r*Nr���repeat) rr"r�r�rr\r7rr�r6)r�� variables�input�tabler#�values r(� truth_tabler/�s�����h0�/�Y�/�/�/�I� �4�=�=�D� �d�O� ,� ,��Z��5E�5E���� �F�3�y�>�>� 2� 2� 2�E������ � �d�3�y�$�#7�#7�8�8�9�9�� � ��t�*�*�e�#� #� #� #� #��K�K�K�K� �r*c�d�d}t|��D]\}}|||kr |dkr|}�dS�|S)zm Checks if a pair of minterms differs by only one bit. If yes, returns index, else returns `-1`. r�)r�)�minterm1�minterm2�indexrhrvs r(� _check_pairr4#sV�� �E��(�#�#�����1� ��� � � ���{�{�����r�r� � �Lr*c�L���fd�t|��D��}t|�S)zh Converts a term in the expansion of a function from binary to its variable form (for SOP). c�h��g|].\}}|dk� |dkr�|nt�|����/S)r�rYr:�ru�n�valr+s �r(rwz'_convert_to_varsSOP.<locals>.<listcomp>9�I��� :� :� :���3��q��� �1�H�H�I�a�L�L�#�i��l�*;�*;�08��r*)r�r1)�mintermr+�temps ` r(r�r�4s=���  :� :� :� :�#�G�,�,� :� :� :�D� ��:�r*c�L���fd�t|��D��}t|�S)zh Converts a term in the expansion of a function from binary to its variable form (for POS). c�h��g|].\}}|dk� |dkr�|nt�|����/S)r�rr:r7s �r(rwz'_convert_to_varsPOS.<locals>.<listcomp>Cr:r*)r�r7)�maxtermr+r<s ` r(r�r�>s=���  :� :� :� :�#�G�,�,� :� :� :�D� �t�9�r*c�^���fd�t|��D��}|stSt|�S)z� Converts a term in the expansion of a function from binary to its variable form (for ANF). Parameters ========== term : list of 1's and 0's (complementation pattern) variables : list of variables c�2��g|]\}}|dk� �|��S)rYr,)rur8�tr+s �r(rwz'_convert_to_varsANF.<locals>.<listcomp>Ts&��� ?� ?� ?�T�Q���Q���I�a�L���r*)r�r r1)r#r+r<s ` r(�_convert_to_varsANFrCHs<��� @� ?� ?� ?�Y�t�_�_� ?� ?� ?�D� ��� � ��:�r*c�T��d��fd�td�z��D��D��S)zu Returns a list of lists, with all possible combinations of n zeros and ones with an odd number of ones. c�>�g|]}t|��dzdk�|��Sr���sum�rur&s r(rwz)_get_odd_parity_terms.<locals>.<listcomp>a�'�� L� L� L�!�C��F�F�Q�J�!�O�O�A�O�O�Or*c�0��g|]}t|�����Sr,�r�rurvr8s �r(rwz)_get_odd_parity_terms.<locals>.<listcomp>a�!���8�8�8�q��Q�� � �8�8�8r*r�rr�r8s`r(r�r�\�9��� M� L�8�8�8�8�E�!�Q�$�K�K�8�8�8� L� L� L�Lr*c�T��d��fd�td�z��D��D��S)zv Returns a list of lists, with all possible combinations of n zeros and ones with an even number of ones. c�>�g|]}t|��dzdk�|��S)rrrFrHs r(rwz*_get_even_parity_terms.<locals>.<listcomp>irIr*c�0��g|]}t|�����Sr,rKrLs �r(rwz*_get_even_parity_terms.<locals>.<listcomp>irMr*rrNrOs`r(r�r�drPr*c����sgSg}ttt�������}tt��}t ���D]9\}}t d�|D����}||�|���:t�d��}t|��D]u}||D]j} ||dzD]\} t�| �| ��} | dkr8dx|| <|| <�| dd�} d| | <| |vr|�| ���]�k�v|rt|��}|� �fd�|D����|S)z� Reduces a set of minterms, if possible, to a simplified set of minterms with one less variable in the terms using QM method. c3�&K�|] }|dk�dV�� dS)rYNr,)rurBs r(r[z$_simplified_pairs.<locals>.<genexpr>{s&����-�-��a�1�f�f�1�f�f�f�f�-�-r*rrYr�Nr�c�$��g|] }|��|�� Sr/r,)rurv�termss �r(rwz%_simplified_pairs.<locals>.<listcomp>�s���E�E�E�!�q�}�U�1�X�}�}�}r*) r6rrr\rr�rGr�r4�_simplified_pairsr8) rW�simplified_terms�todo�termdictr8r#�onesr+rErvror3�newterms ` r(rXrXls���� ��� ��� ��c�%�j�j�!�!� "� "�D��4� � �H��U�#�#�!�!���4��-�-�d�-�-�-�-�-�������a� � � � ��E�!�H� � �I� �9� � � 9� 9���!�� 9� 9�A��a��c�]� 9� 9��#�E�!�H�e�A�h�7�7���B�;�;�(,�,�D��G�d�1�g�#�A�h�q�q�q�k�G�%&�G�E�N��&6�6�6�(�/�/��8�8�8�� 9� 9��?�,�-=�>�>�����E�E�E�E�t�E�E�E�F�F�F� �r*c �������������|sgSt|��}t�����fd�t|��D���dg�z�dg|z}t���D]l\}}t|��D]W\}}td�t ||��D����r+d�||<�|xxdz cc<||xxdz cc<�X�md}|�r�d}t|��D]�} || r��| �t|��D]�} | | kr�|| r||| || krj�| �t��fd�t���D����r9d|| <d}t���D]"\}}|rd�| |<�|xxdzcc<�#����i} t���D�] ���r��| vr | ��n!��fd�t|��D����| �<t���D]����kr���r�����kr��| vr | ��n!��fd �t|��D����| �<t��fd �t|��D����rGd��<d}t���D]0\}}|r)�|�rd�|�<||xxdzcc<�1���� |s�d} d } t���D]���}|| kr�} |} �| d kry| dkrst���D]c\}}|| krXt| | ��D]B\}}|r;�||r-d�||<d}||xxdzcc<�|xxdzcc<�C�d|�����fd �t���D��S) z� After the truth table has been sufficiently simplified, use the prime implicant table method to recognize and eliminate redundant pairs, and return the essential arguments. c���g|]}dg�z�� S)rr,)rur8�nl1s �r(rwz#_rem_redundancy.<locals>.<listcomp>�s���0�0�0�Q�!��S��0�0�0r*rc3�4K�|]\}}|dkp||kV��dS)r�Nr,)rurB�mts r(r[z"_rem_redundancy.<locals>.<genexpr>�s3����C�C���B�1��6�$�Q�"�W�C�C�C�C�C�Cr*rYTFc3�<�K�|]}�|�|kV��dSr/r,)rur8�row�row2s ��r(r[z"_rem_redundancy.<locals>.<genexpr>�s0�����E�E�Q�t�A�w�#�a�&�0�E�E�E�E�E�Er*c�,��g|]}�|���Sr,r,)rurv�coli� dommatrixs ��r(rwz#_rem_redundancy.<locals>.<listcomp>�s"���E�E�E�!�9�Q�<��-�E�E�Er*c�,��g|]}�|���Sr,r,)rurv�col2irhs ��r(rwz#_rem_redundancy.<locals>.<listcomp>�s"���#O�#O�#O�A�I�a�L��$7�#O�#O�#Or*c3�<�K�|]}�|�|kV��dSr/r,)rur8�col�col2s ��r(r[z"_rem_redundancy.<locals>.<genexpr>�s0�����H�H�Q�s�1�v��a��0�H�H�H�H�H�Hr*r�c�0��g|]}�|� �|��Sr,r,)rurv�colcount�l1s ��r(rwz#_rem_redundancy.<locals>.<listcomp>�s&��� 5� 5� 5�a��!�� 5�B�q�E� 5� 5� 5r*)r\rrr�rr�)rprW�nterms�rowcount�primei�prime�termir#�anythingchanged�rowi�row2i�colcache�maxterms� bestcolidxrkrlrmrjrorgrhr`rdres` @@@@@@@@@r(�_rem_redundancyr|�s������������� ��� � ��Z�Z�F� �b�'�'�C�1�0�0�0�%��-�-�0�0�0�I��s�3�w�H��s�6�z�H�"�2���%�%� ���$�U�+�+� %� %�K�E�4��C�C�#�e�T�2B�2B�C�C�C�C�C� %�+,� �%� ��(��� � � �A�%� � � ������1�$�����  %��O� �E6����&�M�M� :� :�D���~� :���o��"�6�]�]� :� :�E��u�}�}��$��}�X�d�^�x�X]��=^�=^�(��/���E�E�E�E�E�%��*�*�E�E�E�E�E�:�./�H�U�O�.2�O�1:�4���:�:� ���#(�!:�?@�I�e�$4�V�$<�$,�V�$4�$4�$4��$9�$4�$4�$4�������#�J�J� 9� 9�D���~� 9��8�#�#�"�4�.�C�C�E�E�E�E�E�u�V�}�}�E�E�E�C�%(�H�T�N�"�3�Z�Z�9�9�E��u�}�}��%��}�h�t�n�PX�Y^�P_�>_�>_� �H�,�,�#+�E�?�D�D�#O�#O�#O�#O�#O��v���#O�#O�#O�D�.2�H�U�O��H�H�H�H�H�%��-�-�H�H�H�H�H�9�./�H�U�O�.2�O�/8����9�9� ��t�#'�!9�I�e�,<�U�,C�!9�>?�I�e�$4�U�$;�$,�U�O�O�O�q�$8�O�O�O����� 6��H��J��c� � � !� !���T�N���x�<�<�!%�J� �H���R���H�q�L�L�%.�r�]�]�6�6�M�F�E���+�+�+4�X�j�5I�+J�+J�6�6�K�E�4�#�6� �%�(8��(@�6�;<� �%� 0�� 8�26�� (�����1� 4���� (�� 0� 0� 0�A� 5� 0� 0� 0���K �E6�N 6� 5� 5� 5� 5�5��:�:� 5� 5� 5�5r*c�<��g}t|��}|D�]�}t|t��r$|�t ||�����<t|t ��r�t |��}|���D]}|�|���tdt|�����D]U}t t||������� |��|��fd�|D�����V��t|t tf��rZt|��|kr#td�|������|�t |������xtd���|S)Nr�r)c� ��g|] }�|�� Sr,r,)rur(�ds �r(rwz%_input_to_binlist.<locals>.<listcomp> s���8�8�8���!��8�8�8r*zTEach term must contain {bits} bits as there are {bits} variables (or be an integer).)�bitsz2A term list can only contain lists, ints or dicts.)r\r"r!r�rrr6�keysr�rr��updater�r5�formatr%) � inputlistr+�binlistr�r9� nonspecvars�keyrBrs @r(�_input_to_binlistr��s�����G� �y�>�>�D��/�/�� �c�3� � � /� �N�N�4��T�?�?� +� +� +� +� ��T� "� "� /��y�/�/�K��x�x�z�z� (� (���"�"�3�'�'�'�'��V�C� �,<�,<�=�=�=� :� :����[�!�,�,�-�-������ � � ����8�8�8�8�i�8�8�8�9�9�9�9� :���d�E�]� +� +� /��3�x�x�4��� �"$�$*�F��F�$5�$5�7�7�7� �N�N�4��9�9� %� %� %� %��.�/�/� /� �Nr*Nc���|stSttt|����}t ||��}t |pg|��}|D]}||vrt d|z����t |||��S)a� The SOPform function uses simplified_pairs and a redundant group- eliminating algorithm to convert the list of all input combos that generate '1' (the minterms) into the smallest sum-of-products form. The variables must be given as the first argument. Return a logical :py:class:`~.Or` function (i.e., the "sum of products" or "SOP" form) that gives the desired outcome. If there are inputs that can be ignored, pass them as a list, too. The result will be one of the (perhaps many) functions that satisfy the conditions. Examples ======== >>> from sympy.logic import SOPform >>> from sympy import symbols >>> w, x, y, z = symbols('w x y z') >>> minterms = [[0, 0, 0, 1], [0, 0, 1, 1], ... [0, 1, 1, 1], [1, 0, 1, 1], [1, 1, 1, 1]] >>> dontcares = [[0, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 1]] >>> SOPform([w, x, y, z], minterms, dontcares) (y & z) | (~w & ~x) The terms can also be represented as integers: >>> minterms = [1, 3, 7, 11, 15] >>> dontcares = [0, 2, 5] >>> SOPform([w, x, y, z], minterms, dontcares) (y & z) | (~w & ~x) They can also be specified using dicts, which does not have to be fully specified: >>> minterms = [{w: 0, x: 1}, {y: 1, z: 1, x: 0}] >>> SOPform([w, x, y, z], minterms) (x & ~w) | (y & z & ~x) Or a combination: >>> minterms = [4, 7, 11, [1, 1, 1, 1]] >>> dontcares = [{w : 0, x : 0, y: 0}, 5] >>> SOPform([w, x, y, z], minterms, dontcares) (w & y & z) | (~w & ~y) | (x & z & ~w) See also ======== POSform References ========== .. [1] https://en.wikipedia.org/wiki/Quine-McCluskey_algorithm .. [2] https://en.wikipedia.org/wiki/Don%27t-care_term �#%s in minterms is also in dontcares)r!r�r�rr�r5� _sop_form)r+�minterms� dontcaresrs r(�SOPformr� s���x ��� ��c�'�9�-�-�.�.�I�!��9�5�5�H�!�9�?��Y�?�?�I� �H�H�� ��=�=��B�Q�F�G�G� G� � �Y��)� 4� 4�4r*c�r��t||z��}t||��}t�fd�|D���S)Nc�0��g|]}t|�����Sr,)r��rurhr+s �r(rwz_sop_form.<locals>.<listcomp>e s$���E�E�E�a�#�A�y�1�1�E�E�Er*)rXr|r7)r+r�r�rl� essentials` r(r�r�b sD��� �H�y�0� 1� 1�C���X�.�.�I� �E�E�E�E�9�E�E�E� F�Fr*c����|stSttt������t |���}t |pg���}|D]}||vrt d|z����g}t dt������D].}t|��}||vr||vr|� |���/t||z��}t||��}t�fd�|D���S)a� The POSform function uses simplified_pairs and a redundant-group eliminating algorithm to convert the list of all input combinations that generate '1' (the minterms) into the smallest product-of-sums form. The variables must be given as the first argument. Return a logical :py:class:`~.And` function (i.e., the "product of sums" or "POS" form) that gives the desired outcome. If there are inputs that can be ignored, pass them as a list, too. The result will be one of the (perhaps many) functions that satisfy the conditions. Examples ======== >>> from sympy.logic import POSform >>> from sympy import symbols >>> w, x, y, z = symbols('w x y z') >>> minterms = [[0, 0, 0, 1], [0, 0, 1, 1], [0, 1, 1, 1], ... [1, 0, 1, 1], [1, 1, 1, 1]] >>> dontcares = [[0, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 1]] >>> POSform([w, x, y, z], minterms, dontcares) z & (y | ~w) The terms can also be represented as integers: >>> minterms = [1, 3, 7, 11, 15] >>> dontcares = [0, 2, 5] >>> POSform([w, x, y, z], minterms, dontcares) z & (y | ~w) They can also be specified using dicts, which does not have to be fully specified: >>> minterms = [{w: 0, x: 1}, {y: 1, z: 1, x: 0}] >>> POSform([w, x, y, z], minterms) (x | y) & (x | z) & (~w | ~x) Or a combination: >>> minterms = [4, 7, 11, [1, 1, 1, 1]] >>> dontcares = [{w : 0, x : 0, y: 0}, 5] >>> POSform([w, x, y, z], minterms, dontcares) (w | x) & (y | ~w) & (z | ~y) See also ======== SOPform References ========== .. [1] https://en.wikipedia.org/wiki/Quine-McCluskey_algorithm .. [2] https://en.wikipedia.org/wiki/Don%27t-care_term r�r�r)c�0��g|]}t|�����Sr,)r�r�s �r(rwzPOSform.<locals>.<listcomp>� s$���F�F�F�q�$�Q� �2�2�F�F�Fr*) r!r�r�rr�r5rr\r6r�rXr|r1)r+r�r�rrzrBrlr�s` r(�POSformr�h s���x ��� ��c�'�9�-�-�.�.�I� ��9�5�5�H�!�9�?��Y�?�?�I� �H�H�� ��=�=��B�Q�F�G�G� G� ��H� �V�C� �N�N� 3� 3� 3���� ��G�G�� �X� � �A�Y�$6�$6� �O�O�A� � � �� �H�y�0� 1� 1�C���X�.�.�I� �F�F�F�F�I�F�F�F� G�Gr*c���t���}t|��}|d|zkrtd||fz���ttt������t |��}g}t td|�����D]&\}}||dkr|�|���'t�fd�|D��ddi�S) a� The ANFform function converts the list of truth values to Algebraic Normal Form (ANF). The variables must be given as the first argument. Return True, False, logical :py:class:`~.And` function (i.e., the "Zhegalkin monomial") or logical :py:class:`~.Xor` function (i.e., the "Zhegalkin polynomial"). When True and False are represented by 1 and 0, respectively, then :py:class:`~.And` is multiplication and :py:class:`~.Xor` is addition. Formally a "Zhegalkin monomial" is the product (logical And) of a finite set of distinct variables, including the empty set whose product is denoted 1 (True). A "Zhegalkin polynomial" is the sum (logical Xor) of a set of Zhegalkin monomials, with the empty set denoted by 0 (False). Parameters ========== variables : list of variables truthvalues : list of 1's and 0's (result column of truth table) Examples ======== >>> from sympy.logic.boolalg import ANFform >>> from sympy.abc import x, y >>> ANFform([x], [1, 0]) x ^ True >>> ANFform([x, y], [0, 1, 1, 1]) x ^ y ^ (x & y) References ========== .. [1] https://en.wikipedia.org/wiki/Zhegalkin_polynomial rz8The number of truth values must be equal to 2^%d, got %dr�r)rYc�0��g|]}t|�����Sr,)rCr�s �r(rwzANFform.<locals>.<listcomp>� s$���B�B�B�q�$�Q� �2�2�B�B�Br*r�F) r\r5r�r�r� anf_coeffsr�rr�rE)r+� truthvalues�n_vars�n_values�coeffsrWrvrBs` r(�ANFformr�� s����T��^�^�F��;���H��1��;����"�%+�X�$6�7�8�8� 8��c�'�9�-�-�.�.�I� � � $� $�F� �E��'�&��8�8�8�9�9�����1� �!�9��>�>� �L�L��O�O�O�� �B�B�B�B�E�B�B�B� "� � "� "�"r*c��d�t|����}t|��dz }t|��d|zkrtdt|��z���d�|D��}t|��D]t}g}td||z dz z��D]U}|�|d|zt t d�|d|z|d|zdz����z���V|}�u|dS)a� Convert a list of truth values of some boolean expression to the list of coefficients of the polynomial mod 2 (exclusive disjunction) representing the boolean expression in ANF (i.e., the "Zhegalkin polynomial"). There are `2^n` possible Zhegalkin monomials in `n` variables, since each monomial is fully specified by the presence or absence of each variable. We can enumerate all the monomials. For example, boolean function with four variables ``(a, b, c, d)`` can contain up to `2^4 = 16` monomials. The 13-th monomial is the product ``a & b & d``, because 13 in binary is 1, 1, 0, 1. A given monomial's presence or absence in a polynomial corresponds to that monomial's coefficient being 1 or 0 respectively. Examples ======== >>> from sympy.logic.boolalg import anf_coeffs, bool_monomial, Xor >>> from sympy.abc import a, b, c >>> truthvalues = [0, 1, 1, 0, 0, 1, 0, 1] >>> coeffs = anf_coeffs(truthvalues) >>> coeffs [0, 1, 1, 0, 0, 0, 1, 0] >>> polynomial = Xor(*[ ... bool_monomial(k, [a, b, c]) ... for k, coeff in enumerate(coeffs) if coeff == 1 ... ]) >>> polynomial b ^ c ^ (a & b) z{:b}rYrz9The number of truth values must be a power of two, got %dc��g|]}|g��Sr,r,r's r(rwzanf_coeffs.<locals>.<listcomp>" s�� '� '� '�a�q�c� '� '� 'r*c� �||z Sr/r,)rh�ys r(r�zanf_coeffs.<locals>.<lambda>( s ��a��c�r*r)r�r\r5rrr�r6r�)r�rkr8r�rv�tmpros r(r�r�� s.��H � � �c�+�&�&�'�'�A� �A���� �A� �;���1�a�4����"�$'� �$4�$4�5�6�6� 6�(� '�;� '� '� '�F� �1�X�X�������q�Q�q�S��U�|�$�$� I� I�A� �J�J�v�a��c�{��S�)�)�6�!�A�#�;��q��s�1�u� �F�F�G�G�H� I� I� I� I���� �!�9�r*c���t|t��rt|t|����}t t t |����}t||��S)a� Return the k-th minterm. Minterms are numbered by a binary encoding of the complementation pattern of the variables. This convention assigns the value 1 to the direct form and 0 to the complemented form. Parameters ========== k : int or list of 1's and 0's (complementation pattern) variables : list of variables Examples ======== >>> from sympy.logic.boolalg import bool_minterm >>> from sympy.abc import x, y, z >>> bool_minterm([1, 0, 1], [x, y, z]) x & z & ~y >>> bool_minterm(6, [x, y, z]) x & y & ~z References ========== .. [1] https://en.wikipedia.org/wiki/Canonical_normal_form#Indexing_minterms )r"r!rr\r�r�rr��rEr+s r(� bool_mintermr�. �R��<�!�S���$� ��C� �N�N� #� #���c�'�9�-�-�.�.�I� �q�)� ,� ,�,r*c���t|t��rt|t|����}t t t |����}t||��S)a� Return the k-th maxterm. Each maxterm is assigned an index based on the opposite conventional binary encoding used for minterms. The maxterm convention assigns the value 0 to the direct form and 1 to the complemented form. Parameters ========== k : int or list of 1's and 0's (complementation pattern) variables : list of variables Examples ======== >>> from sympy.logic.boolalg import bool_maxterm >>> from sympy.abc import x, y, z >>> bool_maxterm([1, 0, 1], [x, y, z]) y | ~x | ~z >>> bool_maxterm(6, [x, y, z]) z | ~x | ~y References ========== .. [1] https://en.wikipedia.org/wiki/Canonical_normal_form#Indexing_maxterms )r"r!rr\r�r�rr�r�s r(� bool_maxtermr�R r�r*c���t|t��rt|t|����}t t t |����}t||��S)aR Return the k-th monomial. Monomials are numbered by a binary encoding of the presence and absences of the variables. This convention assigns the value 1 to the presence of variable and 0 to the absence of variable. Each boolean function can be uniquely represented by a Zhegalkin Polynomial (Algebraic Normal Form). The Zhegalkin Polynomial of the boolean function with `n` variables can contain up to `2^n` monomials. We can enumerate all the monomials. Each monomial is fully specified by the presence or absence of each variable. For example, boolean function with four variables ``(a, b, c, d)`` can contain up to `2^4 = 16` monomials. The 13-th monomial is the product ``a & b & d``, because 13 in binary is 1, 1, 0, 1. Parameters ========== k : int or list of 1's and 0's variables : list of variables Examples ======== >>> from sympy.logic.boolalg import bool_monomial >>> from sympy.abc import x, y, z >>> bool_monomial([1, 0, 1], [x, y, z]) x & z >>> bool_monomial(6, [x, y, z]) x & y )r"r!rr\r�r�rrCr�s r(� bool_monomialr�v sS��F�!�S���$� ��C� �N�N� #� #���c�'�9�-�-�.�.�I� �q�)� ,� ,�,r*c��t|t��s|hSt��jt t |j���S)z�Helper to find logical predicates in BooleanFunctions. A logical predicate is defined here as anything within a BooleanFunction that is not a BooleanFunction itself. )r"r�rxryr�r�rzr�s r(r�r�� s=�� �d�O� ,� ,���v� � �3�5�5�;��-�t�y�9�9� ;�;r*c���|dvrtd���t|��}|rOd}|dkrt|��}n|dkrt|��}|r t d�|jD����r|Sddlm}|rh|�|��}dd l m }tt||����} |� tt|| ������}t!|t"��s|Si} i} dd lm} |�|��}|�7t|��}|�|�|����|rc|���} | jrF| ��}| | |<|| | <| j}||vr't1|��| |<|�|��|�c|� | ��}|�|� | ��}t5|��}|s(t7|��d kr|� | ��S|�Jt5|��}|�|��|s$t7|��d krt5|��}d }t9t;|��d �d���\}}||z}d�|D��}t=|||��}|� t=|||����fd�|D��}ng�t7|��dt7|��dz zk}|dks|�&|r$t?||���� | ��StA||���� | ��S)ak This function simplifies a boolean function to its simplified version in SOP or POS form. The return type is an :py:class:`~.Or` or :py:class:`~.And` object in SymPy. Parameters ========== expr : Boolean form : string (``'cnf'`` or ``'dnf'``) or ``None`` (default). If ``'cnf'`` or ``'dnf'``, the simplest expression in the corresponding normal form is returned; if ``None``, the answer is returned according to the form with fewest args (in CNF by default). deep : bool (default ``True``) Indicates whether to recursively simplify any non-boolean functions contained within the input. force : bool (default ``False``) As the simplifications require exponential time in the number of variables, there is by default a limit on expressions with 8 variables. When the expression has more than 8 variables only symbolical simplification (controlled by ``deep``) is made. By setting ``force`` to ``True``, this limit is removed. Be aware that this can lead to very long simplification times. dontcare : Boolean Optimize expression under the assumption that inputs where this expression is true are don't care. This is useful in e.g. Piecewise conditions, where later conditions do not need to consider inputs that are converted by previous conditions. For example, if a previous condition is ``And(A, B)``, the simplification of expr can be made with don't cares for ``And(A, B)``. Examples ======== >>> from sympy.logic import simplify_logic >>> from sympy.abc import x, y, z >>> b = (~x & ~y & ~z) | ( ~x & ~y & z) >>> simplify_logic(b) ~x & ~y >>> simplify_logic(x | y, dontcare=y) x References ========== .. [1] https://en.wikipedia.org/wiki/Don%27t-care_term )Nr�rzform can be cnf or dnf onlyFr�rc3�4K�|]}t|��V��dSr/)r�)rur�s r(r[z!simplify_logic.<locals>.<genexpr>� s<����$�$��&�a�=�=�$�$�$�$�$�$r*rrIr�)�DummyNr�c� �|dvS)Nrvr,r�s r(r�z simplify_logic.<locals>.<lambda> s ��a�=�.@�r*Trc�"�g|] }|dkrdnd�� S)TrYrr,r�s r(rwz"simplify_logic.<locals>.<listcomp>! s$��*�*�*�1�a�4�i�i���Q�*�*�*r*c���g|]}|�v�|�� Sr,r,)rurB� dctruthtables �r(rwz"simplify_logic.<locals>.<listcomp>% s#���E�E�E�A�q� �/D�/D�a�/D�/D�/Dr*rrY)!r5rr�rrrzrLrJrOr�rTr�r�r7rr�r"r�rr�r�r]r r�r;r�r�r\rr�_get_truthtabler�r�)r��formr�r��dontcare�form_okrJr+rTrk�repl�undor��varr�nvar� dcvariablesrr(� truthtable�bigr�s @r(r�r�� s����l �'�'�'��6�7�7�7� �4�=�=�D� � ��� �5�=�=��T�l�l�G�G� �U�]�]��T�l�l�G� � �s�$�$���$�$�$�$�$� ��K�0�0�0�0�0�0� �6��J�J�z�*�*� �4�4�4�4�4�4� �#�h� �*�*� +� +���}�}�T�#�i��"3�"3�4�4�5�5�� �d�O� ,� ,��� � �D� �D�'�'�'�'�'�'�� � �:�&�&�I����8�$�$�������� �3�3�4�4�4� � '��m�m�o�o�� � � '�����A��D��G��D��I��;�D��y� � � ��V�V��T� �� � ��&�&�&� � '� �=�=�� � �D����$�$�T�*�*��!��&�&�I� �#�S��^�^�a�'�'��}�}�T�"�"�"���&�x�0�0� �����%�%�%�� ��Y���!�+�+�(��.�.�I��H� �� �"�"�$@�$@�� N� N� N�D�A�q��A��I�*�*��*�*�*�A� ��D�!�,�,�J���&�q�(�A�6�6� �E�E�E�E��E�E�E� � �� � �j�/�/�a�C� �N�N�Q�$6�7� 8�C� �u�}�}�� �� ���J� �=�=�F�F�t�L�L�L� �9�j�,� 7� 7� @� @�� F� F�Fr*c�����|������fd���fd��|ggg��D��}|ggkrgS|S)zN Return a list of all combinations leading to a True result for ``expr``. c�����rN������fd�|D��}|��fd�|D�����|��S|S)Nc���g|]?}|dtu�|d��ti��dg|dzg��@Sr�)r!r7�rurvr(s �r(rwz4_get_truthtable.<locals>._get_tt.<locals>.<listcomp>5 sL���`�`�`�q�a�PQ�d�Z_�N_�N_�A�a�D�M�M�1�e�*�-�-��s�Q�q�T�z�:�N_�N_�N_r*c���g|]?}|dtu�|d��ti��dg|dzg��@Sr�)r!r7r r�s �r(rwz4_get_truthtable.<locals>._get_tt.<locals>.<listcomp>6 sN���d�d�d�1�RS�TU�RV�^c�Rc�Rc��1�����4�y�1�1�A�3��1��:�>�Rc�Rc�Rcr*)r]r8)�inputs�tabr(�_get_tt� _variabless @��r(r�z _get_truthtable.<locals>._get_tt2 sn���� � ���� � �A�`�`�`�`�F�`�`�`�C� �J�J�d�d�d�d��d�d�d� e� e� e��7�3�<�<� �� r*c�6��g|]}|d� �|dz��Sr�r,)rurE�consts �r(rwz#_get_truthtable.<locals>.<listcomp>9 s*��� ?� ?� ?�A�!�A�$� ?�5�1�Q�4�<� ?� ?� ?r*)�copy)r+r�r�r�r�r�s ` @@r(r�r�. su��������!�!�J������� @� ?� ?� ?���4��*��!6�!6� ?� ?� ?�C� �r�d�{�{�� �� r*c ���|j}ttt|d�|D��������}|jD]�}|jr||dxxdz cc<� |jr"||jddxxdz cc<�It|j��td�|jD����f}|jD]s}|jr3||dxxdz cc<||d|xxdz cc<�<|jr"||jddxxdz cc<�etd�����tt��}tt|� ������D]n\}}ttd �|d� ��D������|d<|t|���|���o|S) a� Assign a 5-item fingerprint to each symbol in the equation: [ # of times it appeared as a Symbol; # of times it appeared as a Not(symbol); # of times it appeared as a Symbol in an And or Or; # of times it appeared as a Not(Symbol) in an And or Or; a sorted tuple of tuples, (i, j, k), where i is the number of arguments in an And or Or with which it appeared as a Symbol, and j is the number of arguments that were Not(Symbol); k is the number of times that (i, j) was seen. ] Examples ======== >>> from sympy.logic.boolalg import _finger as finger >>> from sympy import And, Or, Not, Xor, to_cnf, symbols >>> from sympy.abc import a, b, x, y >>> eq = Or(And(Not(y), a), And(Not(y), b), And(x, y)) >>> dict(finger(eq)) {(0, 0, 1, 0, ((2, 0, 1),)): [x], (0, 0, 1, 0, ((2, 1, 1),)): [a, b], (0, 0, 1, 2, ((2, 0, 1),)): [y]} >>> dict(finger(x & ~y)) {(0, 1, 0, 0, ()): [y], (1, 0, 0, 0, ()): [x]} In the following, the (5, 2, 6) means that there were 6 Or functions in which a symbol appeared as itself amongst 5 arguments in which there were also 2 negated symbols, e.g. ``(a0 | a1 | a2 | ~a3 | ~a4)`` is counted once for a0, a1 and a2. >>> dict(finger(to_cnf(Xor(*symbols('a:5'))))) {(0, 0, 8, 8, ((5, 0, 1), (5, 2, 6), (5, 4, 1))): [a0, a1, a2, a3, a4]} The equation must not have more than one level of nesting: >>> dict(finger(And(Or(x, y), y))) {(0, 0, 1, 0, ((2, 0, 1),)): [x], (1, 0, 1, 0, ((2, 0, 1),)): [y]} >>> dict(finger(And(Or(x, And(a, x)), y))) Traceback (most recent call last): ... NotImplementedError: unexpected level of nesting So y and x have unique fingerprints, but a and b do not. c�F�g|]}dgdztt��gz��S)r�)rr!)ru�fis r(rwz_finger.<locals>.<listcomp>p s.��A�A�A��1�#�a�%�;�s�#3�#3�"4�4�A�A�Ar*rrYc3�@K�|]}t|t��V��dSr/)r"r;)ru�ais r(r[z_finger.<locals>.<genexpr>w s,���� F� F���B��!4�!4� F� F� F� F� F� Fr*rr�r�zunexpected level of nestingc� �g|] \}}||fz�� Sr,r,)rurvros r(rwz_finger.<locals>.<listcomp>� s"��A�A�A�4�1�a�a�1�$�h�A�A�Ar*)r[rr6r�rzrsrwr\rGrNrr�iter�itemsr��sortedr�) �eqr)rr��or��invrEr(s r(�_fingerr�@ s���^ ��A� �T�#�a�A�A�q�A�A�A�B�B� C� C�D�D�A� �W�M�M�� �;� M� �a�D��G�G�G�q�L�G�G�G�G� �X� M� �a�f�Q�i�L��O�O�O�q� �O�O�O�O��A�F� � �S� F� F�q�v� F� F� F�F�F�F�A��f� M� M���<�M��b�E�!�H�H�H��M�H�H�H��b�E�"�I�a�L�L�L�A�%�L�L�L�L��Y�M��b�g�a�j�M�!�$�$�$��)�$�$�$�$�-�.K�L�L�L� M� �d� � �C���Q�W�W�Y�Y���(�(� � ���1��f�A�A�1�R�5�;�;�=�=�A�A�A�B�B�C�C��"�� �E�!�H�H� ���Q����� �Jr*c�l�d�}t|��}t|��}|||��}|r||fS|S)a Return the simplified version of *bool1*, and the mapping of variables that makes the two expressions *bool1* and *bool2* represent the same logical behaviour for some correspondence between the variables of each. If more than one mappings of this sort exist, one of them is returned. For example, ``And(x, y)`` is logically equivalent to ``And(a, b)`` for the mapping ``{x: a, y: b}`` or ``{x: b, y: a}``. If no such mapping exists, return ``False``. Examples ======== >>> from sympy import SOPform, bool_map, Or, And, Not, Xor >>> from sympy.abc import w, x, y, z, a, b, c, d >>> function1 = SOPform([x, z, y],[[1, 0, 1], [0, 0, 1]]) >>> function2 = SOPform([a, b, c],[[1, 0, 1], [1, 0, 0]]) >>> bool_map(function1, function2) (y & ~z, {y: a, z: b}) The results are not necessarily unique, but they are canonical. Here, ``(w, z)`` could be ``(a, d)`` or ``(d, a)``: >>> eq = Or(And(Not(y), w), And(Not(y), z), And(x, y)) >>> eq2 = Or(And(Not(c), a), And(Not(c), d), And(b, c)) >>> bool_map(eq, eq2) ((x & y) | (w & ~y) | (z & ~y), {w: a, x: b, y: c, z: d}) >>> eq = And(Xor(a, b), c, And(c,d)) >>> bool_map(eq, eq.subs(c, x)) (c & d & (a | b) & (~a | ~b), {a: a, b: b, c: d, d: x}) c��|j|jkrdSt|j��t|j��krdS|jr||iSt |��}t |��}t|��t|��krdSi}|���D]d}||vrdSt||��t||��krdSt ||��D]\}}|||||<��e|S)a:Return the mapping that equates variables between two simplified boolean expressions if possible. By "simplified" we mean that a function has been denested and is either an And (or an Or) whose arguments are either symbols (x), negated symbols (Not(x)), or Or (or an And) whose arguments are only symbols or negated symbols. For example, ``And(x, Not(y), Or(w, Not(z)))``. Basic.match is not robust enough (see issue 4835) so this is a workaround that is valid for simplified boolean expressions NF)r�r\rzrsr�r�r�)r r �f1�f2� matchdictrErvrhs r(�matchzbool_map.<locals>.match� s�� � �)�"5� 5� 5��4� �y�~� � �#�i�n�"5�"5� 5� 5��4� � � *��y�)� )��Y� � �� �Y� � �� �r�7�7�c�"�g�g� � ��5�� ������ (� (�A���{�{��u�u��2�a�5�z�z�S��A��Z�Z�'�'��u�u�!�"�Q�%�(�(� (� (���1�!�!�u�Q�x� �!� � � (��r*)r�)�bool1�bool2r�r�rBrAs r(�bool_mapr�� sT��H'�'�'�R �u���A��u���A� ��a�� � �A����!�t� � �Hr*c�� � �ddlm� m� |�|�|}t|j� fd�d���\}}t |��dkr|St|d�d���\}}d �|D��}|r,t |��d krt |||j|||��}t|||j|||��}|j� fd �t|��D��|z|z�}|S) a� Replace patterns of Relational Parameters ========== rv : Expr Boolean expression patterns : tuple Tuple of tuples, with (pattern to simplify, simplified pattern) with two terms. measure : function Simplification measure. dominatingvalue : Boolean or ``None`` The dominating value for the function of consideration. For example, for :py:class:`~.And` ``S.false`` is dominating. As soon as one expression is ``S.false`` in :py:class:`~.And`, the whole expression is ``S.false``. replacementvalue : Boolean or ``None``, optional The resulting value for the whole expression if one argument evaluates to ``dominatingvalue``. For example, for :py:class:`~.Nand` ``S.false`` is dominating, but in this case the resulting value is ``S.true``. Default is ``None``. If ``replacementvalue`` is ``None`` and ``dominatingvalue`` is not ``None``, ``replacementvalue = dominatingvalue``. threeterm_patterns : tuple, optional Tuple of tuples, with (pattern to simplify, simplified pattern) with three terms. r)rJ� _canonicalNc�$��t|���Sr/rrs �r(r�z4_apply_patternbased_simplification.<locals>.<lambda> s���*�Q� �*C�*C�r*TrrYc�@�td�|jD���� S)Nc3�(K�|] }|jduV��dS)FN)�is_real)rurks r(r[zG_apply_patternbased_simplification.<locals>.<lambda>.<locals>.<genexpr> sE����2K�2K�67�34�)�u�2D�2K�2K�2K�2K�2K�2Kr*)r\r[)rvs r(r�z4_apply_patternbased_simplification.<locals>.<lambda> s;��c�2K�2K�;<�>�2K�2K�2K�/K�/K�+K�r*c��g|] }|j�� Sr,r0r�s r(rwz6_apply_patternbased_simplification.<locals>.<listcomp> s�� $� $� $�1�1�;� $� $� $r*r�c�&��g|] }�|����Sr,r,)rurvr�s �r(rwz6_apply_patternbased_simplification.<locals>.<listcomp> s!���8�8�8�a�J�J�q�M�M�8�8�8r*) rLrJr�rrzr\�,_apply_patternbased_threeterm_simplificationre�*_apply_patternbased_twoterm_simplificationr) r�rFr"�dominatingvalue�replacementvaluer1r<r=� nonRealRelrJr�s @@r(r;r;� sG����N=�<�<�<�<�<�<�<���O�$?�*���r�w� C� C� C� C�"�$�$�$�K�C�� �3�x�x�1�}�}�� ��3�!K�!K�"&�(�(�(�O�C�� %� $�� $� $� $�C��7�c�#�h�h�!�m�m�:�3�.����,�g�7�7�� 5�S�(��G�_�.>�� I� I�C� ���8�8�8�8�7�3�<�<�8�8�8���&�'� )�B� �Ir*c�����ddlm}m}ddlm�m�m�d}|�r1t|��dk�rd}��fd�|D��}tt|����}�fd�|D��} g} tt| ��d��D�]\\} } \} }|D]�\}}g}t| |��D]C\}}t||��}|�|��}|r|�||f���D|r�|D]�\}}|�|��}||kr |gcccSt#|t$��sV|�||��s@|||j���||��z }|dkr| �|| | g|ff��������| r�t+| d �d� ��} | dd }|\}}|���t/|��D]}||=�|�|t1|��kr@|j|kr |jD]}|�|���n|�|��d}|rt|��dk��|S) z- Apply pattern-based two-term simplification.r��Min�Max)rg�Gt� _InequalityTrFc�F��g|]}t|��f��r|jn|��Sr,�r"�reversed)rurjrgr�s ��r(rwz>_apply_patternbased_twoterm_simplification.<locals>.<listcomp>) �2���I�I�I��Z��B��8�4�4�;�q�z�z�!�I�I�Ir*c�H��g|]}t|���r|fn||jf��Sr,r��rurjr�s �r(rwz>_apply_patternbased_twoterm_simplification.<locals>.<listcomp>- �4���V�V�V�Q��A�{�3�3�H����!�Q�Z��V�V�Vr*c��|dSr&r,��pairs r(r�z<_apply_patternbased_twoterm_simplification.<locals>.<lambda>M � ��D��G�r*�r��reverserY)�(sympy.functions.elementary.miscellaneousr�r�rLrgr�r�r\r6rrr�rr r�r�r7r"r�rMrzr��sortr�r;re) r<rFrer�r�r"r�r��changed�rtmp�resultsrv�piro�pj�pattern�simpr��p1�p2�oldexpr�tmpres�np� costsaving� replacement�idx�newrelr3r�rgr�r�s @@@r(r�r� s����� B�A�A�A�A�A�A�A�9�9�9�9�9�9�9�9�9�9��G� �8�c�#�h�h�!�m�m���I�I�I�I�I�S�I�I�I���7�3�<�<� � ��V�V�V�V�RU�V�V�V����".�y�����"B�"B� K� K� �W�a��g�q�"�!)� K� K� �����%�b�"�o�o�6�6�F�B��#�B��m�m�G�$�]�]�7�3�3�F��6�� � �F�G�#4�5�5�5���K�+.� K� K����!�]�]�6�2�2����0�0�%5�#5�5�5�5�5�5�5�5�)�"�c�2�2�K�2�6�6�#�s�;K�;K�K�*1����w�|�1D�)E�)E���PR� � �)S�J�)�A�~�~� '��� �a��V�R�L�/I� J� J� J���/ K�0 � ��W�/C�/C�T�S�S�S�G�"�!�*�Q�-�K�%�K�C�� �H�H�J�J�J�!�#��� � ����J�J��&�&�C��4H�4H�*H�*H��;�$�&�&�#�[�&�&��� � �1� � � � �&��J�J�v�&�&�&��G�q �8�c�#�h�h�!�m�m�r �Jr*c �� �!�"�ddlm}m}ddlm� m�!m�"d}|�r9t|��dk�r%d}� �!fd�|D��}tt|����}g} �"fd�|D��} tt| ��d��D�] \\} } \} }\}}|D]�\}}g}t| ||��D]E\}}}t|||��}|�|��}|r|�||f���F|r�|D]�\}}|�|��}||kr |gcccSt#|t$��sW|�||��sA|||j���||��z }|dkr| �|| | |g|ff�������� | r�t+| d �d� ��} | dd }|\}}|���t/|��D]}||=�|�|t1|��kr@|j|kr |jD]}|�|���n|�|��d}|rt|��dk��%|S) z/ Apply pattern-based three-term simplification.rr�)rf�Ltr�Tr�Fc�F��g|]}t|��f��r|jn|��Sr,r�)rurjrfrs ��r(rwz@_apply_patternbased_threeterm_simplification.<locals>.<listcomp>m r�r*c�H��g|]}t|���r|fn||jf��Sr,r�r�s �r(rwz@_apply_patternbased_threeterm_simplification.<locals>.<listcomp>s r�r*c��|dSr&r,r�s r(r�z>_apply_patternbased_threeterm_simplification.<locals>.<lambda>� r�r*r�rY)rr�r�rLrfrr�r\r6rrr�rr r�r�r7r"r�rMrzr�rr�r;re)#r<rFrer�r�r"r�r�rrrrvrrorrE�pkrr r�r r �p3r r rrrrrr3r�rfrr�s# @@@r(r�r�b s-����� B�A�A�A�A�A�A�A�9�9�9�9�9�9�9�9�9�9��G� �8�c�#�h�h�!�m�m���I�I�I�I�I�S�I�I�I���7�3�<�<� � ����V�V�V�V�RU�V�V�V��+7� �$����+K�+K� N� N� '�W�a��g�q�"�w��2�!)� N� N� �����")�"�b�"�"5�"5�6�6�J�B��B�#�B��B�/�/�G�$�]�]�7�3�3�F��6�� � �F�G�#4�5�5�5���N�+.� N� N����!�]�]�6�2�2����0�0�%5�#5�5�5�5�5�5�5�5�)�"�c�2�2�N�2�6�6�#�s�;K�;K�N�*1����w�|�1D�)E�)E���PR� � �)S�J�)�A�~�~� '��� �a��A�Y��O�/L� M� M� M���/ N�0 � ��W�/C�/C�T�S�S�S�G�"�!�*�Q�-�K�%�K�C�� �H�H�J�J�J�!�#��� � ����J�J��&�&�C��4H�4H�*H�*H��;�$�&�&�#�[�&�&��� � �1� � � � �&��J�J�v�&�&�&��G�q �8�c�#�h�h�!�m�m�r �Jr*c� �ddlm}ddlm}m}m}m}m}m}ddl m }ddl m }m } |d��} |d��} |d��} t|| | ��|| | ����tft|| | ��|| | ����tft|| | ��|| | ����|| | ��ft|| | ��|| | ����|| | ��ft|| | ��|| | ����|| | ��ft|| | ��|| | ����|| | ��ft|| | ��|| | ����|| | ��ft|| | ��|| | ����t!|| t"j��|| t"j����ft|| | ��|| | ����|| | | | ����ft|| | ��|| | ����t'| | k|| | ��|| | ����ft|| | ��|| | ����|| | | | ����ft|| | ��|| | ����|| || | ����ft|| | ��|| | ����t'| | k|| | ��|| | ����ft|| | ��|| | ����|| || | ����ft|| | ��|| | ����t'|| | ��|| | ��t'| | ktt!|| | ��|| | ��������ft|| | ��|| | ����t'|| | ��|| | ��t'| | ktt!|| | ��|| | ��������ft|| | ��|| | ����t'| | ktt!|| | ��|| | ������ft|| | ��|| | ����t'| | ktt!|| | ��|| | ������ft|| | ��|| | ����t'| | ktt!|| | ��|| | ������ft|| | ��|| | ����t'| | ktt!|| | ��|| | ������ft|| | ��|| | ����t'|| | ��|| | ��t��ft|| | ��|| | ����t'| dk||| ��| ��t��ft|| | ��|| | ����t'| dk||| ��| ��t��ff} | S) z Two-term patterns for And.r��Wild�rorprgr�rfr��Absr�r�rBr)� sympy.corerrLrorprgr�rfr�$sympy.functions.elementary.complexesrrr�r�r r!r1rrr�)rrorprgr�rfrrr�r�r�rBr� _matchers_ands r(r9r9� s�� ������<�<�<�<�<�<�<�<�<�<�<�<�<�<�<�<�8�8�8�8�8�8�A�A�A�A�A�A�A�A� ��S� � �A� ��S� � �A� ��S� � �A��B�B�q�!�H�H�b�b��A�h�h�/�/��7��B�B�q�!�H�H�b�b��A�h�h�/�/��7��B�B�q�!�H�H�b�b��A�h�h�/�/���A�q���:��B�B�q�!�H�H�b�b��A�h�h�/�/���A�q���:��B�B�q�!�H�H�b�b��A�h�h�/�/���A�q���:��B�B�q�!�H�H�b�b��A�h�h�/�/���A�q���:��B�B�q�!�H�H�b�b��A�h�h�/�/���A�q���:��B�B�q�!�H�H�b�b��Q�B�i�i�0�0�#�b�b��A�F�m�m�R�R��1�6�]�]�2S�2S�T��B�B�q�!�H�H�b�b��A�h�h�/�/���A�s�s�1�a�y�y�1A�1A�B��B�B�q�!�H�H�b�b��A�h�h�/�/��Q��U�B�B�q�!�H�H�b�b��A�h�h�1O�1O�P��B�B�q�!�H�H�b�b��A�h�h�/�/���A�s�s�1�a�y�y�1A�1A�B��B�B�q�!�H�H�b�b��A�h�h�/�/���A�s�s�1�a�y�y�1A�1A�B��B�B�q�!�H�H�b�b��A�h�h�/�/��Q��U�B�B�q�!�H�H�b�b��A�h�h�1O�1O�P��B�B�q�!�H�H�b�b��A�h�h�/�/���A�s�s�1�a�y�y�1A�1A�B��B�B�q�!�H�H�b�b��A�h�h�/�/��R�R��1�X�X�r�r�!�Q�x�x��Q�QR�U�TY�[^�_a�_a�bc�ef�_g�_g�ik�ik�lm�op�iq�iq�[r�[r�Is�Is�1t�1t�u��B�B�q�!�H�H�b�b��A�h�h�/�/��R�R��1�X�X�r�r�!�Q�x�x��Q�QR�U�TY�[^�_a�_a�bc�ef�_g�_g�ik�ik�lm�op�iq�iq�[r�[r�Is�Is�1t�1t�u��B�B�q�!�H�H�b�b��A�h�h�/�/��Q��U�E�3�r�r�!�Q�x�x�QS�QS�TU�WX�QY�QY�CZ�CZ�1[�1[�\��B�B�q�!�H�H�b�b��A�h�h�/�/��Q��U�E�3�r�r�!�Q�x�x�QS�QS�TU�WX�QY�QY�CZ�CZ�1[�1[�\��B�B�q�!�H�H�b�b��A�h�h�/�/��Q�!�V�U�C���1�a���RT�RT�UV�XY�RZ�RZ�D[�D[�1\�1\�]��B�B�q�!�H�H�b�b��A�h�h�/�/��Q�!�V�U�C���1�a���RT�RT�UV�XY�RZ�RZ�D[�D[�1\�1\�]��B�B�q�!�H�H�b�b��A�h�h�/�/��R�R��1�X�X�r�r�!�Q�x�x��1O�1O�P��B�B�q�!�H�H�b�b�!��Q�i�i�0�0�#�a�!�e�R�R���A����]�]�E�2R�2R�S��B�B�q�!�H�H�b�b�!��Q�i�i�0�0�#�a�1�f�b�b���Q����m�m�U�2S�2S�T�? �M�B �r*c�� �ddlm}ddlm}m}m}|d��}|d��}|d��}t |||��|||��|||����tft |||��|||��|||����tft |||��|||��|||����tft |||��|||��|||����t|||��|||����ft |||��|||��|||����t|||��|||����ft |||��|||��|||����t|||��|||����ft |||��|||��|||����t|||��|||����ft |||��|||��|||����t|||��|||����ft |||��|||��|||����t|||��|||����ft |||��|||��|||����t|||��|||����ft |||��|||��|||����t|||��|||����ft |||��|||��|||����t|||��|||����ft |||��|||��|||����t|||��|||����ft |||��|||��|||����t|||��|||����ft |||��|||��|||����t|||��|||����ft |||��|||��|||����t|||��|||����ff}|S)z Three-term patterns for And.rr)rorgr�r�rBr) r rrLrorgr�r r!r1)rrorgr�r�rBrr"s r(r:r:� s�� ������0�0�0�0�0�0�0�0�0�0� ��S� � �A� ��S� � �A� ��S� � �A��B�B�q�!�H�H�b�b��A�h�h���1�a���9�9�5�A��B�B�q�!�H�H�b�b��A�h�h���1�a���9�9�5�A��B�B�q�!�H�H�b�b��A�h�h���1�a���9�9�5�A��B�B�q�!�H�H�b�b��A�h�h���1�a���9�9�3�r�r�!�Q�x�x���A�q���;R�;R�S��B�B�q�!�H�H�b�b��A�h�h���1�a���9�9�3�r�r�!�Q�x�x���A�q���;R�;R�S��B�B�q�!�H�H�b�b��A�h�h���1�a���9�9�3�r�r�!�Q�x�x���A�q���;R�;R�S��B�B�q�!�H�H�b�b��A�h�h���1�a���9�9�3�r�r�!�Q�x�x���A�q���;R�;R�S��B�B�q�!�H�H�b�b��A�h�h���1�a���9�9�3�r�r�!�Q�x�x���A�q���;R�;R�S��B�B�q�!�H�H�b�b��A�h�h���1�a���9�9�3�r�r�!�Q�x�x���A�q���;R�;R�S��B�B�q�!�H�H�b�b��A�h�h���1�a���9�9�3�r�r�!�Q�x�x���A�q���;R�;R�S��B�B�q�!�H�H�b�b��A�h�h���1�a���9�9�3�r�r�!�Q�x�x���A�q���;R�;R�S��B�B�q�!�H�H�b�b��A�h�h���1�a���9�9�3�r�r�!�Q�x�x���A�q���;R�;R�S��B�B�q�!�H�H�b�b��A�h�h���1�a���9�9�3�r�r�!�Q�x�x���A�q���;R�;R�S��B�B�q�!�H�H�b�b��A�h�h���1�a���9�9�3�r�r�!�Q�x�x���A�q���;R�;R�S��B�B�q�!�H�H�b�b��A�h�h���1�a���9�9�3�r�r�!�Q�x�x���A�q���;R�;R�S��B�B�q�!�H�H�b�b��A�h�h���1�a���9�9�3�r�r�!�Q�x�x���A�q���;R�;R�S�3�M�6 �r*c �� �ddlm}ddlm}m}m}m}m}m}ddl m }ddl m }m } |d��} |d��} |d��} t|| | ��|| | ����tft|| | ��|| | ����tft|| | ��|| | ����|| | ��ft|| | ��|| | ����|| | ��ft|| | ��|| | ����|| | ��ft|| | ��|| | ����|| | ��ft|| | ��|| | ����|| | ��ft|| | ��|| | ����t!|| | ��t|| | ����ft|| | ��|| | ����t!|| | ��|| | ��t��ft|| | ��|| | ����|| || | ����ft|| | ��|| | ����t!| | k|| | ��|| | ����ft|| | ��|| | ����|| || | ����ft|| | ��|| | ����|| | | | ����ft|| | ��|| | ����t!| | k|| | ��|| | ����ft|| | ��|| | ����|| | | | ����ft|| | ��|| | ����t!| | ktt#|| | ��|| | ������ft|| | ��|| | ����t!| | ktt#|| | ��|| | ������ft|| | ��|| | ����t!| | ktt#|| | ��|| | ������ft|| | ��|| | ����t!| | ktt#|| | ��|| | ������ft|| | ��|| | ����t!| | ktt#|| | ��|| | ������ft|| | ��|| | ����t!| | ktt#|| | ��|| | ������ft|| | ��|| | ����t!| dk||| ��| ��t��ft|| | ��|| | ����t!| dk||| ��| ��t��ff} | S) z Two-term patterns for Or.rrrrr�r�rBr)r rrLrorprgr�rfrr!rrr�r�r r r�r7)rrorprgr�rfrrr�r�r�rBr� _matchers_ors r(rkrk s��� ������<�<�<�<�<�<�<�<�<�<�<�<�<�<�<�<�8�8�8�8�8�8�A�A�A�A�A�A�A�A� ��S� � �A� ��S� � �A� ��S� � �A��2�2�a��8�8�R�R��1�X�X�.�.��5��2�2�a��8�8�R�R��1�X�X�.�.��5� �2�2�a��8�8�R�R��1�X�X�.�.���1�a���9��2�2�a��8�8�R�R��1�X�X�.�.���1�a���9��2�2�a��8�8�R�R��1�X�X�.�.���1�a���9��2�2�a��8�8�R�R��1�X�X�.�.���1�a���9��2�2�a��8�8�R�R��1�X�X�.�.���1�a���9��2�2�a��8�8�R�R��1�X�X�.�.��B�B�q�!�H�H�d�B�B�q�!�H�H�0M�0M�N��2�2�a��8�8�R�R��1�X�X�.�.��B�B�q�!�H�H�b�b��A�h�h��0M�0M�N��2�2�a��8�8�R�R��1�X�X�.�.���1�c�c�!�Q�i�i�0@�0@�A��2�2�a��8�8�R�R��1�X�X�.�.��A��E�2�2�a��8�8�R�R��1�X�X�0N�0N�O��2�2�a��8�8�R�R��1�X�X�.�.���1�c�c�!�Q�i�i�0@�0@�A��2�2�a��8�8�R�R��1�X�X�.�.���1�c�c�!�Q�i�i�0@�0@�A��2�2�a��8�8�R�R��1�X�X�.�.��A��F�B�B�q�!�H�H�b�b��A�h�h�0O�0O�P��2�2�a��8�8�R�R��1�X�X�.�.���1�c�c�!�Q�i�i�0@�0@�A��2�2�a��8�8�R�R��1�X�X�.�.��A��F�D�"�R�R��1�X�X�r�r�RS�UV�x�x�BX�BX�0Y�0Y�Z��2�2�a��8�8�R�R��1�X�X�.�.��A��F�D�"�R�R��1�X�X�r�r�RS�UV�x�x�BX�BX�0Y�0Y�Z��2�2�a��8�8�R�R��1�X�X�.�.��A��E�4��B�B�q�!�H�H�b�b�QR�TU�h�h�AW�AW�0X�0X�Y��2�2�a��8�8�R�R��1�X�X�.�.��A��E�4��B�B�q�!�H�H�b�b�QR�TU�h�h�AW�AW�0X�0X�Y��2�2�a��8�8�R�R��1�X�X�.�.��A��F�D�"�R�R��1�X�X�r�r�RS�UV�x�x�BX�BX�0Y�0Y�Z��2�2�a��8�8�R�R��1�X�X�.�.��A��F�D�"�R�R��1�X�X�r�r�RS�UV�x�x�BX�BX�0Y�0Y�Z��2�2�a��8�8�R�R��A�2�Y�Y�/�/��Q�!�V�R�R���A����]�]�D�1Q�1Q�R��2�2�a��8�8�R�R��A�2�Y�Y�/�/��Q��U�B�B�s�s�1�v�v�q�M�M�4�1P�1P�Q�E#�L�H �r*c��ddlm}m}ddlm}ddlm}m}m}m }m }m }|d��} |d��} |d��} t|| | ��|| | ����|| | ��ft|| | ��|| | ����|| | ��ft|| | ��|| | ����|| | ��ft|| | ��|| | ����|| | ��ft|| | ��|| | ����|| | ��ft|| | ��|| | ����|| | ��ft|| | ��|| | ����t|| || | ����|| || | ������ft|| | ��|| | ����t| | kt|| | ��|| | ����t|| | ��|| | ������ft|| | ��|| | ����t|| || | ����|| || | ������ft|| | ��|| | ����t|| || | ����|| || | ������ft|| | ��|| | ����t| | kt|| | ��|| | ����t|| | ��|| | ������ft|| | ��|| | ����t|| || | ����|| || | ������ff } | S)z Two-term patterns for Xor.rr�rrr�rBr)rr�r�r rrLrorprgr�rfrr r1r�) r�r�rrorprgr�rfrr�rBr� _matchers_xors r(r�r�8 s-��B�A�A�A�A�A�A�A�������<�<�<�<�<�<�<�<�<�<�<�<�<�<�<�<� ��S� � �A� ��S� � �A� ��S� � �A��B�B�q�!�H�H�b�b��A�h�h�/�/���A�q���:��B�B�q�!�H�H�b�b��A�h�h�/�/���A�q���:��B�B�q�!�H�H�b�b��A�h�h�/�/���A�q���:��B�B�q�!�H�H�b�b��A�h�h�/�/���A�q���:��B�B�q�!�H�H�b�b��A�h�h�/�/���A�q���:��B�B�q�!�H�H�b�b��A�h�h�/�/���A�q���:� �B�B�q�!�H�H�b�b��A�h�h�/�/��"�"�Q���A�q� � �*�*�B�B�q�#�#�a��)�)�,<�,<�=�=�?��B�B�q�!�H�H�b�b��A�h�h�/�/��!�a�%��R�R��1�X�X�r�r�!�Q�x�x�!8�!8��b�b��A�h�h���1�a���1�1�3�3�4��B�B�q�!�H�H�b�b��A�h�h�/�/��"�"�Q���A�q� � �*�*�B�B�q�#�#�a��)�)�,<�,<�=�=�?��B�B�q�!�H�H�b�b��A�h�h�/�/��"�"�Q���A�q� � �*�*�B�B�q�#�#�a��)�)�,<�,<�=�=�?��B�B�q�!�H�H�b�b��A�h�h�/�/��!�a�%��R�R��1�X�X�r�r�!�Q�x�x�!8�!8��b�b��A�h�h���1�a���1�1�3�3�4��B�B�q�!�H�H�b�b��A�h�h�/�/��"�"�Q���A�q� � �*�*�B�B�q�#�#�a��)�)�,<�,<�=�=�?�7�M�< �r*c��ddlm}ddlm}m}t |t ��s|S|�||��r|S|}|j}t|��dkr|S|� ��}|d|fd���� |d���\}}|s|S|stSg} |D�]$\} } } } | tjur>| tjurt }n�|�|| ��dkr|| k}n�|| k}n�|�|| ��dk} |�|| ��dk}| r)|r'| jr|| k}nut'| |k|| k��}n\| rt'| |k|| k��}nA|r'| jr|| k}n1t'| |k|| k��}nt'| |k|| k��}| �|����&t+| �S) zKreturn a simplified version of univariate boolean expression, else ``expr``rrrnrYFr'T)� err_on_Eq)rrrLrorpr"r�rOr[r\r]� _intervalsr!r�NegativeInfinity�Infinityr rd� is_infiniter1r�r7)r�rrorprrgrh�okrvrzr�rB�_�incl_a�incl_bs r(r�r�f s6��>�>�>�>�>�>�,�,�,�,�,�,�,�,� �d�O� ,� ,��� � �z�z�"�b����� � �A� �>�D� �4�y�y�A�~�~��� ��� � �A� �I�q�!�f�u� � � ��j��d�j�+�+� �B�� ���� ��� � �D���� ��1�a�� ��"� "� "��A�J�������6�6�!�Q�<�<�4�'�'��a��A�A��Q��A�A��f�f�Q��l�l�d�*�F��f�f�Q��l�l�d�*�F�� &�&� &��=�,��a��A�A��A��F�A��F�+�+�A�A�� &���Q���A��&�&���� &��=�+��Q��A�A��A��E�1��6�*�*�A�A���A��q�1�u�%�%�� � � �A����� �t�9�r*c���t|t��std���t|t��r3t |j��t d�|jD����zSdS)a� Return the total number of inputs for the logic gates realizing the Boolean expression. Returns ======= int Number of gate inputs Note ==== Not all Boolean functions count as gate here, only those that are considered to be standard gates. These are: :py:class:`~.And`, :py:class:`~.Or`, :py:class:`~.Xor`, :py:class:`~.Not`, and :py:class:`~.ITE` (multiplexer). :py:class:`~.Nand`, :py:class:`~.Nor`, and :py:class:`~.Xnor` will be evaluated to ``Not(And())`` etc. Examples ======== >>> from sympy.logic import And, Or, Nand, Not, gateinputcount >>> from sympy.abc import x, y, z >>> expr = And(x, y) >>> gateinputcount(expr) 2 >>> gateinputcount(Or(expr, z)) 4 Note that ``Nand`` is automatically evaluated to ``Not(And())`` so >>> gateinputcount(Nand(x, y, z)) 4 >>> gateinputcount(Not(And(x, y, z))) 4 Although this can be avoided by using ``evaluate=False`` >>> gateinputcount(Nand(x, y, z, evaluate=False)) 3 Also note that a comparison will count as a Boolean variable: >>> gateinputcount(And(x > z, y >= 2)) 2 As will a symbol: >>> gateinputcount(x) 0 zExpression must be Booleanc3�4K�|]}t|��V��dSr/)�gateinputcount)rurhs r(r[z!gateinputcount.<locals>.<genexpr>� s*����#I�#I�!�N�1�$5�$5�#I�#I�#I�#I�#I�#Ir*r)r"r$r%� BooleanGatesr\rzrGr�s r(r4r4� sj��j �d�G� $� $�6��4�5�5�5��$� �%�%�J��4�9�~�~��#I�#I�t�y�#I�#I�#I� I� I�I�I� �1r*r�)FFr/)NTFN)NN)tr�� collectionsr� itertoolsrrrr�sympy.core.addr�sympy.core.basicr �sympy.core.cacher �sympy.core.containersr �sympy.core.decoratorsr r �sympy.core.functionrr�sympy.core.kindrr�sympy.core.numbersr�sympy.core.operationsr�sympy.core.singletonrr�sympy.core.sortingr�sympy.core.sympifyrrr�sympy.utilities.iterablesrr�sympy.utilities.miscrr)r$r�r�r�r r!r�r�r1r7r;rErcrOr�r@rPr�r�r�r�r�r�rSr�r�rUr�rr�r�r�rrr�r�rr$�integer_to_termr/r4r�r�rCr�r�rXr|r�r�r�r�r�r�r�r�r�r�r�r�r�r�r;r�r�r9r:rkr�r�r5r4r,r*r(�<module>rGs�����$�#�#�#�#�#�@�@�@�@�@�@�@�@�@�@�@�@�������"�"�"�"�"�"�$�$�$�$�$�$�'�'�'�'�'�'�E�E�E�E�E�E�E�E�7�7�7�7�7�7�7�7�3�3�3�3�3�3�3�3�%�%�%�%�%�%�+�+�+�+�+�+�-�-�-�-�-�-�-�-�&�&�&�&�&�&�B�B�B�B�B�B�B�B�B�B�0�0�0�0�0�0�0�0�+�+�+�+�+�+�&@�&@�&@�R�E�E�E�E�E�e�E�E���E�P1�1�1�1�1�'�1�1�1�hq�q�q�q�q�+��q�q�q�q�hG�G�G�G�G�;�)�G�G�G�G�T�{�}�}��� ���� ��� ���7�7����V�V�V�V�V�k�7�V�V�V�r]�]�]�]�]�)�_�]�]�]�@g3�g3�g3�g3�g3��O�g3�g3�g3�Tq:�q:�q:�q:�q:�/�q:�q:�q:�hE(�E(�E(�E(�E(�/�E(�E(�E(�P�����?����:�����/����D�����?����>Q:�Q:�Q:�Q:�Q:�o�Q:�Q:�Q:�hQ,�Q,�Q,�Q,�Q,��Q,�Q,�Q,�hr>�r>�r>�r>�r>�/�r>�r>�r>�j���������>���"���"(�(�(�"(�(�(�&)�)�)�&���0)"�)"�)"�)"�X!�!�!�!�2'�'�'�'�T%(�%(�%(�%(�P5�5�5�p.�.�.�.�b#�#�#�(#�#�#�,���((�(�(�2���D���67�7�7�.��A�A�A�A�H���"���������(M�M�M�M�M�M�(�(�(�Vc6�c6�c6�L���4H5�H5�H5�H5�VG�G�G� NH�NH�NH�NH�b;"�;"�;"�|4�4�4�n!-�!-�!-�H!-�!-�!-�H&-�&-�&-�R <� <� <�@G�@G�@G�@G�F���$D�D�D�NR �R �R �n9=�:>�?�?�?�?�DA�A�A�HA�A�A�H �.�.� ��.�b �'�'� ��'�T �1�1� ��1�h �*�*� ��*�Z/�/�/�h�R��d�C��d�C�8� �9 �9 �9 �9 �9 r*
Memory