ó
¡¼™\c           @  sç   d  Z  d d l m Z m Z d d l m Z d d l m Z d d l m	 Z	 m
 Z
 m Z m Z m Z m Z m Z d d l m Z m Z d „  Z d „  Z d	 „  Z i  d
 „ Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d S(   s&  Implementation of DPLL algorithm

Further improvements: eliminate calls to pl_true, implement branching rules,
efficient unit propagation.

References:
  - https://en.wikipedia.org/wiki/DPLL_algorithm
  - https://www.researchgate.net/publication/242384772_Implementations_of_the_DPLL_Algorithm
iÿÿÿÿ(   t   print_functiont   division(   t   range(   t   default_sort_key(   t   Ort   Nott	   conjunctst	   disjunctst   to_cnft   to_int_reprt   _find_predicates(   t   pl_truet   literal_symbolc         C  s¿   t  t |  ƒ ƒ } t | k r" t St t |  ƒ d t ƒ} t t d t | ƒ d ƒ ƒ } t	 | | ƒ } t
 | | i  ƒ } | s„ | Si  } x. | D]& } | j i | | | | d 6ƒ q‘ W| S(   s>  
    Check satisfiability of a propositional sentence.
    It returns a model rather than True when it succeeds

    >>> from sympy.abc import A, B
    >>> from sympy.logic.algorithms.dpll import dpll_satisfiable
    >>> dpll_satisfiable(A & ~B)
    {A: True, B: False}
    >>> dpll_satisfiable(A & ~A)
    False

    t   keyi   (   R   R   t   Falset   sortedR
   R   t   setR   t   lenR	   t   dpll_int_reprt   update(   t   exprt   clausest   symbolst   symbols_int_reprt   clauses_int_reprt   resultt   outputR   (    (    s:   lib/python2.7/site-packages/sympy/logic/algorithms/dpll.pyt   dpll_satisfiable   s    $c   
      C  sÕ  t  |  | ƒ \ } } x_ | rv | j i | | 6ƒ | j | ƒ | sO | } n  t |  | ƒ }  t  |  | ƒ \ } } q Wt | |  ƒ \ } } x_ | rí | j i | | 6ƒ | j | ƒ | sÆ | } n  t |  | ƒ }  t | |  ƒ \ } } q Wg  } xI |  D]A } t | | ƒ } | t k r t S| t k	 rû | j | ƒ qû qû W| sJ| S|  sT| S| j	 ƒ  } | j
 ƒ  } | j i t | 6ƒ | j i t | 6ƒ | }	 t t | | ƒ | | ƒ pÔt t | t | ƒ ƒ |	 | ƒ S(   sí   
    Compute satisfiability in a partial model.
    Clauses is an array of conjuncts.

    >>> from sympy.abc import A, B, D
    >>> from sympy.logic.algorithms.dpll import dpll
    >>> dpll([A, B, D], [A, B], {D: False})
    False

    (   t   find_unit_clauseR   t   removet   unit_propagatet   find_pure_symbolR   R   t   Truet   appendt   popt   copyt   dpllR   (
   R   R   t   modelt   Pt   valuet   unknown_clausest   ct   valt
   model_copyt   symbols_copy(    (    s:   lib/python2.7/site-packages/sympy/logic/algorithms/dpll.pyR$   /   sD    	
	
c   
      C  sË  t  |  | ƒ \ } } x_ | rv | j i | | 6ƒ | j | ƒ | sO | } n  t |  | ƒ }  t  |  | ƒ \ } } q Wt | |  ƒ \ } } x_ | rí | j i | | 6ƒ | j | ƒ | sÆ | } n  t |  | ƒ }  t | |  ƒ \ } } q Wg  } xI |  D]A } t | | ƒ } | t k r t S| t k	 rû | j | ƒ qû qû W| sJ| S| j	 ƒ  } | j
 ƒ  } | j i t | 6ƒ | j i t | 6ƒ | j
 ƒ  }	 t t | | ƒ | | ƒ pÊt t | | ƒ |	 | ƒ S(   sô   
    Compute satisfiability in a partial model.
    Arguments are expected to be in integer representation

    >>> from sympy.logic.algorithms.dpll import dpll_int_repr
    >>> dpll_int_repr([{1}, {2}, {3}], {1, 2}, {3: False})
    False

    (   t   find_unit_clause_int_reprR   R   t   unit_propagate_int_reprt   find_pure_symbol_int_reprt   pl_true_int_reprR   R    R!   R"   R#   R   (
   R   R   R%   R&   R'   R(   R)   R*   R+   R,   (    (    s:   lib/python2.7/site-packages/sympy/logic/algorithms/dpll.pyR   `   s@    	
	
c         C  s„   t  } xw |  D]o } | d k  rH | j | ƒ } | d k	 rW | } qW n | j | ƒ } | t k rg t S| d k r d } q q W| S(   sf  
    Lightweight version of pl_true.
    Argument clause represents the set of args of an Or clause. This is used
    inside dpll_int_repr, it is not meant to be used directly.

    >>> from sympy.logic.algorithms.dpll import pl_true_int_repr
    >>> pl_true_int_repr({1, 2}, {1: False})
    >>> pl_true_int_repr({1, 2}, {1: False, 2: False})
    False

    i    N(   R   t   gett   NoneR    (   t   clauseR%   R   t   litt   p(    (    s:   lib/python2.7/site-packages/sympy/logic/algorithms/dpll.pyR0      s    c         C  sµ   g  } x¨ |  D]  } | j  t k r5 | j | ƒ q n  xu | j D]] } | | k rŒ | j t g  | j D] } | | k re | ^ qe Œ  ƒ Pn  | | k r? Pq? q? W| j | ƒ q W| S(   s  
    Returns an equivalent set of clauses
    If a set of clauses contains the unit clause l, the other clauses are
    simplified by the application of the two following rules:

      1. every clause containing l is removed
      2. in every clause that contains ~l this literal is deleted

    Arguments are expected to be in CNF.

    >>> from sympy import symbols
    >>> from sympy.abc import A, B, D
    >>> from sympy.logic.algorithms.dpll import unit_propagate
    >>> unit_propagate([A | B, D | ~B, B], B)
    [D, B]

    (   t   funcR   R!   t   args(   R   t   symbolR   R)   t   argt   x(    (    s:   lib/python2.7/site-packages/sympy/logic/algorithms/dpll.pyR   «   s    6c         C  s1   | h } g  |  D] } | | k r | | ^ q S(   sï   
    Same as unit_propagate, but arguments are expected to be in integer
    representation

    >>> from sympy.logic.algorithms.dpll import unit_propagate_int_repr
    >>> unit_propagate_int_repr([{1, 2}, {3, -2}, {2}], 2)
    [{3}]

    (    (   R   t   st   negatedR3   (    (    s:   lib/python2.7/site-packages/sympy/logic/algorithms/dpll.pyR.   Í   s    

c         C  s“   xŒ |  D]„ } t  t  } } xX | D]P } | rI | t | ƒ k rI t } n  | r! t | ƒ t | ƒ k r! t } q! q! W| | k r | | f Sq Wd S(   sE  
    Find a symbol and its value if it appears only as a positive literal
    (or only as a negative) in clauses.

    >>> from sympy import symbols
    >>> from sympy.abc import A, B, D
    >>> from sympy.logic.algorithms.dpll import find_pure_symbol
    >>> find_pure_symbol([A, B, D], [A|~B,~B|~D,D|A])
    (A, True)

    N(   NN(   R   R   R    R   R2   (   R   R(   t   symt	   found_post	   found_negR)   (    (    s:   lib/python2.7/site-packages/sympy/logic/algorithms/dpll.pyR   Û   s    	c         C  s™   t  ƒ  j | Œ  } | j |  ƒ } | j g  |  D] } | ^ q. ƒ } x% | D] } | | k rK | t f SqK Wx& | D] } | | k rs | t f Sqs Wd S(   s  
    Same as find_pure_symbol, but arguments are expected
    to be in integer representation

    >>> from sympy.logic.algorithms.dpll import find_pure_symbol_int_repr
    >>> find_pure_symbol_int_repr({1,2,3},
    ...     [{1, -2}, {-2, -3}, {3, 1}])
    (1, True)

    N(   NN(   R   t   uniont   intersectionR    R   R2   (   R   R(   t   all_symbolsR>   R;   R?   R5   (    (    s:   lib/python2.7/site-packages/sympy/logic/algorithms/dpll.pyR/   ó   s    #c         C  s„   x} |  D]u } d } xP t  | ƒ D]B } t | ƒ } | | k r  | d 7} | t | t ƒ } } q  q  W| d k r | | f Sq Wd S(   s%  
    A unit clause has only 1 variable that is not bound in the model.

    >>> from sympy import symbols
    >>> from sympy.abc import A, B, D
    >>> from sympy.logic.algorithms.dpll import find_unit_clause
    >>> find_unit_clause([A | B | D, B | ~D, A | ~B], {A:True})
    (B, False)

    i    i   N(   NN(   R   R   t
   isinstanceR   R2   (   R   R%   R3   t   num_not_in_modelt   literalR=   R&   R'   (    (    s:   lib/python2.7/site-packages/sympy/logic/algorithms/dpll.pyR   
  s    
c         C  s   t  | ƒ t  d „  | Dƒ ƒ B} xZ |  D]R } | | } t | ƒ d k r' | j ƒ  } | d k  rl | t f S| t f Sq' q' Wd S(   s  
    Same as find_unit_clause, but arguments are expected to be in
    integer representation.

    >>> from sympy.logic.algorithms.dpll import find_unit_clause_int_repr
    >>> find_unit_clause_int_repr([{1, 2, 3},
    ...     {2, -3}, {1, -2}], {1: True})
    (2, False)

    c         s  s   |  ] } | Vq d  S(   N(    (   t   .0R=   (    (    s:   lib/python2.7/site-packages/sympy/logic/algorithms/dpll.pys	   <genexpr>,  s    i   i    N(   NN(   R   R   R"   R   R    R2   (   R   R%   t   boundR3   t   unboundR5   (    (    s:   lib/python2.7/site-packages/sympy/logic/algorithms/dpll.pyR-   !  s     
N(   t   __doc__t
   __future__R    R   t   sympy.core.compatibilityR   t   sympyR   t   sympy.logic.boolalgR   R   R   R   R   R	   R
   t   sympy.logic.inferenceR   R   R   R$   R   R0   R   R.   R   R/   R   R-   (    (    (    s:   lib/python2.7/site-packages/sympy/logic/algorithms/dpll.pyt   <module>	   s   4		1	0	"				