B
    >?[d                 @   s  d Z ddlmZmZ ddlmZ ddlZddlZddlZddl	Z	ddl
mZ ddlmZ ddlmZ ddlmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZ G d	d
 d
e Z!G dd de!Z"dd Z#dd Z$dd Z%dd Z&eG dd de'Z(e)dZ*e)dZ+e)dej,Z-dd Z.d1ddZ/eG dd de'Z0eG d d! d!e1Z2d"Z3d2d#d$Z4d3d&d'Z5d4d(d)Z6d5d*d+Z7d6d,d-Z8e9d.kre8d/dd0 dS )7zK
This module provides data structures for representing first-order
models.
    )print_functionunicode_literals)pformatN)string_types)	decorator)python_2_unicode_compatible)AbstractVariableExpressionAllExpression
ExpressionAndExpressionApplicationExpressionEqualityExpressionExistsExpressionIffExpressionImpExpressionIndividualVariableExpressionLambdaExpressionNegatedExpressionOrExpressionVariable	is_indvarc               @   s   e Zd ZdS )ErrorN)__name__
__module____qualname__ r   r   0lib/python3.7/site-packages/nltk/sem/evaluate.pyr   0   s   r   c               @   s   e Zd ZdS )	UndefinedN)r   r   r   r   r   r   r   r   4   s   r   c             O   sp   t jd dkrt| }n
t| }tt|d |}|dd rft  x|	 D ]}td|  qRW | ||S )Nr      tracez%s => %s)
sysversion_infoinspectZgetfullargspecZ
getargspecdictzippopprintitems)fargskwZargspecditemr   r   r   r   8   s    
r   c             C   sN   t | dkrdS tdd | D r>t t| t t| kr>dS td|  dS )z
    Check whether a set represents a relation (of any arity).

    :param s: a set containing tuples of str elements
    :type s: set
    :rtype: bool
        r   Tc             s   s   | ]}t |tV  qd S )N)
isinstancetuple).0Zelr   r   r   	<genexpr>Q   s    zis_rel.<locals>.<genexpr>z.Set %r contains sequences of different lengthsN)lenallmaxmin
ValueError)sr   r   r   is_relE   s
    	*r7   c             C   sT   t  }xH| D ]@}t|tr(||f qt|trB|t| q|| qW |S )aR  
    Convert a set containing individuals (strings or numbers) into a set of
    unary tuples. Any tuples of strings already in the set are passed through
    unchanged.

    For example:
      - set(['a', 'b']) => set([('a',), ('b',)])
      - set([3, 27]) => set([('3',), ('27',)])

    :type s: set
    :rtype: set of tuple of str
    )setr-   r   addintstr)r6   newelemr   r   r   set2relW   s    


r>   c             C   s    t | dkrdS t t| d S )ze
    Check the arity of a relation.
    :type rel: set of tuples
    :rtype: int of tuple of str
    r   )r1   list)Zrelr   r   r   arityo   s    r@   c                   sT   e Zd ZdZ fddZdd Zdd Zedd	 Zed
d Z	e
dd Z  ZS )	Valuationa  
    A dictionary which represents a model-theoretic Valuation of non-logical constants.
    Keys are strings representing the constants to be interpreted, and values correspond
    to individuals (represented as strings) and n-ary relations (represented as sets of tuples
    of strings).

    An instance of ``Valuation`` will raise a KeyError exception (i.e.,
    just behave like a standard  dictionary) if indexed with an expression that
    is not in its list of symbols.
    c                sx   t t|   xd|D ]\\}}t|ts0t|tr:|| |< qt|trRt|| |< qtj	d||f dd}t
|qW dS )z=
        :param xs: a list of (symbol, value) pairs.
        zGError in initializing Valuation. Unrecognized value for symbol '%s':
%sB   )widthN)superrA   __init__r-   r   boolr8   r>   textwrapZfillr5   )selfZxsZsymvalmsg)	__class__r   r   rE      s    

zValuation.__init__c             C   s$   || krt | |S td| d S )NzUnknown expression: '%s')r#   __getitem__r   )rH   keyr   r   r   rL      s    zValuation.__getitem__c             C   s   t | S )N)r   )rH   r   r   r   __str__   s    zValuation.__str__c             C   sR   g }xD|   D ]8}t|tr(|| qt|ts|dd |D  qW t|S )z7Set-theoretic domain of the value-space of a Valuation.c             S   s"   g | ]}|D ]}|d k	r|qqS )Nr   )r/   Ztuple_r=   r   r   r   
<listcomp>   s    z$Valuation.domain.<locals>.<listcomp>)valuesr-   r   appendrF   extendr8   )rH   ZdomrI   r   r   r   domain   s    

zValuation.domainc             C   s   t |  S )z9The non-logical constants which the Valuation recognizes.)sortedkeys)rH   r   r   r   symbols   s    zValuation.symbolsc             C   s   t |S )N)read_valuation)clsr6   r   r   r   
fromstring   s    zValuation.fromstring)r   r   r   __doc__rE   rL   rN   propertyrS   rV   classmethodrY   __classcell__r   r   )rK   r   rA   z   s   rA   z	\s*=+>\s*z\s*,\s*zg\s*
                                (\([^)]+\))  # tuple-expression
                                \s*c             C   s   t | }|d }|d }|dr|dd }t|}|rvg }x<|D ](}|dd }tt|}|| qHW n
t|}t|}||fS )a  
    Read a line in a valuation file.

    Lines are expected to be of the form::

      noosa => n
      girl => {g1, g2}
      chase => {(b1, g1), (b2, g1), (g1, d1), (g2, d2)}

    :param s: input line
    :type s: str
    :return: a pair (symbol, value)
    :rtype: tuple
    r      {)	_VAL_SPLIT_REsplit
startswith
_TUPLES_REfindallr.   _ELEMENT_SPLIT_RErQ   r8   )r6   piecesZsymbolvalueZtuple_stringsZset_elementsZtselementr   r   r   _read_valuation_line   s    




rj   c          	   C   s   |dk	r|  |} g }xlt|  D ]\\}}| }|ds$|dkrHq$y|t| W q$ tk
r~   td||f Y q$X q$W t|S )a  
    Convert a valuation string into a valuation.

    :param s: a valuation string
    :type s: str
    :param encoding: the encoding of the input string, if it is binary
    :type encoding: str
    :return: a ``nltk.sem`` valuation
    :rtype: Valuation
    N# zUnable to parse line %s: %s)	decode	enumerate
splitlinesstriprc   rQ   rj   r5   rA   )r6   encodingZ
statementsZlinenumliner   r   r   rW      s    
rW   c                   sT   e Zd ZdZd fdd	Zdd Zdd Zdd	d
Zdd Zdd Z	dd Z
  ZS )
Assignmentad  
    A dictionary which represents an assignment of values to variables.

    An assigment can only assign values from its domain.

    If an unknown expression *a* is passed to a model *M*\ 's
    interpretation function *i*, *i* will first check whether *M*\ 's
    valuation assigns an interpretation to *a* as a constant, and if
    this fails, *i* will delegate the interpretation of *a* to
    *g*. *g* only assigns values to individual variables (i.e.,
    members of the class ``IndividualVariableExpression`` in the ``logic``
    module. If a variable is not assigned a value by *g*, it will raise
    an ``Undefined`` exception.

    A variable *Assignment* is a mapping from individual variables to
    entities in the domain. Individual variables are usually indicated
    with the letters ``'x'``, ``'y'``, ``'w'`` and ``'z'``, optionally
    followed by an integer (e.g., ``'x0'``, ``'y332'``).  Assignments are
    created using the ``Assignment`` constructor, which also takes the
    domain as a parameter.

        >>> from nltk.sem.evaluate import Assignment
        >>> dom = set(['u1', 'u2', 'u3', 'u4'])
        >>> g3 = Assignment(dom, [('x', 'u1'), ('y', 'u2')])
        >>> g3 == {'x': 'u1', 'y': 'u2'}
        True

    There is also a ``print`` format for assignments which uses a notation
    closer to that in logic textbooks:

        >>> print(g3)
        g[u1/x][u2/y]

    It is also possible to update an assignment using the ``add`` method:

        >>> dom = set(['u1', 'u2', 'u3', 'u4'])
        >>> g4 = Assignment(dom)
        >>> g4.add('x', 'u1')
        {'x': 'u1'}

    With no arguments, ``purge()`` is equivalent to ``clear()`` on a dictionary:

        >>> g4.purge()
        >>> g4
        {}

    :param domain: the domain of discourse
    :type domain: set
    :param assign: a list of (varname, value) associations
    :type assign: list
    Nc                st   t t|   || _|rbxH|D ]@\}}|| jksBtd|| jf t|sVtd| || |< qW d | _|   d S )Nz'%s' is not in the domain: %sz-Wrong format for an Individual Variable: '%s')rD   rs   rE   rS   AssertionErrorr   variant_addvariant)rH   rS   ZassignvarrI   )rK   r   r   rE   9  s    

zAssignment.__init__c             C   s$   || krt | |S td| d S )Nz"Not recognized as a variable: '%s')r#   rL   r   )rH   rM   r   r   r   rL   I  s    zAssignment.__getitem__c             C   s   t | j}||  |S )N)rs   rS   update)rH   r<   r   r   r   copyO  s    

zAssignment.copyc             C   s    |r| |= n|    |   dS )z
        Remove one or all keys (i.e. logic variables) from an
        assignment, and update ``self.variant``.

        :param var: a Variable acting as a key for the assignment.
        N)clearrv   )rH   rw   r   r   r   purgeT  s
    zAssignment.purgec             C   s4   d}t | j}x |D ]\}}|d||f 7 }qW |S )zQ
        Pretty printing for assignments. {'x', 'u'} appears as 'g[u/x]'
        gz[%s/%s])rT   ru   )rH   Zgstringru   rI   rw   r   r   r   rN   b  s
    
zAssignment.__str__c             C   s:   g }x*|   D ]}|d |d f}|| qW || _dS )zK
        Create a more pretty-printable version of the assignment.
        r^   r   N)r'   rQ   ru   )rH   Zlist_r,   Zpairr   r   r   rv   m  s    zAssignment._addvariantc             C   sD   || j kstd|| j f t|s0td| || |< |   | S )zh
        Add a new variable-value pair to the assignment, and update
        ``self.variant``.

        z%s is not in the domain %sz-Wrong format for an Individual Variable: '%s')rS   rt   r   rv   )rH   rw   rI   r   r   r   r9   x  s
    zAssignment.add)N)N)r   r   r   rZ   rE   rL   ry   r{   rN   rv   r9   r]   r   r   )rK   r   rs     s   4
rs   c               @   sP   e Zd ZdZdd Zdd Zdd Zdd	d
ZdddZdddZ	dddZ
dS )Modela[  
    A first order model is a domain *D* of discourse and a valuation *V*.

    A domain *D* is a set, and a valuation *V* is a map that associates
    expressions with values in the model.
    The domain of *V* should be a subset of *D*.

    Construct a new ``Model``.

    :type domain: set
    :param domain: A set of entities representing the domain of discourse of the model.
    :type valuation: Valuation
    :param valuation: the valuation of the model.
    :param prop: If this is set, then we are building a propositional    model and don't require the domain of *V* to be subset of *D*.
    c             C   s<   t |tst|| _|| _||js8td|j|f d S )NzDThe valuation domain, %s, must be a subset of the model's domain, %s)r-   r8   rt   rS   	valuation
issupersetr   )rH   rS   r~   r   r   r   rE     s    zModel.__init__c             C   s   d| j | jf S )Nz(%r, %r))rS   r~   )rH   r   r   r   __repr__  s    zModel.__repr__c             C   s   d| j | jf S )NzDomain = %s,
Valuation = 
%s)rS   r~   )rH   r   r   r   rN     s    zModel.__str__Nc             C   sn   y:t |}| j|||d}|r8t  td|||f  |S  tk
rh   |rdt  td||f  dS X dS )aA  
        Read input expressions, and provide a handler for ``satisfy``
        that blocks further propagation of the ``Undefined`` error.
        :param expr: An ``Expression`` of ``logic``.
        :type g: Assignment
        :param g: an assignment to individual variables.
        :rtype: bool or 'Undefined'
        )r   z '%s' evaluates to %s under M, %sz'%s' is undefined under M, %sr   N)r
   rY   satisfyr&   r   )rH   exprr|   r   parsedrh   r   r   r   evaluate  s    	
zModel.evaluatec                sP  t |trt| \}}t |trL| }t fdd|D }||kS |j }|j }|| S nt |tr|j	  S t |t
r|j o|j S t |trڈ|j p؈|j S t |tr|j  p|j S t |tr.|j |j kS t |trV|j |j kS t |tr  }	x4jD ]*}
|	|jj|
 |j	|	srdS qrW dS t |tr  }	x4jD ]*}
|	|jj|
 |j	|	rdS qW dS t |tr>i }|jj}x.jD ]$}
|j	 ||
}|||
< qW |S | |S dS )a  
        Recursive interpretation function for a formula of first-order logic.

        Raises an ``Undefined`` error when ``parsed`` is an atomic string
        but is not a symbol or an individual variable.

        :return: Returns a truth value or ``Undefined`` if ``parsed`` is        complex, and calls the interpretation function ``i`` if ``parsed``        is atomic.

        :param parsed: An expression of ``logic``.
        :type g: Assignment
        :param g: an assignment to individual variables.
        c             3   s   | ]} | V  qd S )N)r   )r/   arg)r|   rH   r   r   r0     s    z Model.satisfy.<locals>.<genexpr>FTN)r-   r   Zuncurryr   r   r.   functionZargumentr   Ztermr   firstsecondr   r   r   r   r	   ry   rS   r9   variablenamer   r   i)rH   r   r|   r   r   Z	argumentsfunvalZargvalsZargvalnew_guZcfrw   rI   r   )r|   rH   r   r     sV    




 

zModel.satisfyFc             C   sD   |j j| jjkr| j|j j S t|tr4||j j S td| dS )a  
        An interpretation function.

        Assuming that ``parsed`` is atomic:

        - if ``parsed`` is a non-logical constant, calls the valuation *V*
        - else if ``parsed`` is an individual variable, calls assignment *g*
        - else returns ``Undefined``.

        :param parsed: an ``Expression`` of ``logic``.
        :type g: Assignment
        :param g: an assignment to individual variables.
        :return: a semantic value
        zCan't find a value for %sN)r   r   r~   rV   r-   r   r   )rH   r   r|   r   r   r   r   r     s
    
zModel.ir   c             C   s.  d}|||  }g }t |tr(t|}	n|}	|	| kr|r\t  t|| d||f   x| jD ]}
| }||	j|
 |r|dkr|d }nd}| 	|||}|rt|d|   |dkr|rt|d||f   qd|
|
 |rdt|d|||f   qdW td	d
 |D }ntd|	j|f |S )a  
        Generate the entities from the model's domain that satisfy an open formula.

        :param parsed: an open formula
        :type parsed: Expression
        :param varex: the relevant free individual variable in ``parsed``.
        :type varex: VariableExpression or str
        :param g: a variable assignment
        :type g:  Assignment
        :return: a set of the entities that satisfy ``parsed``.
        z   z'Open formula is '%s' with assignment %sr^   r   z(trying assignment %s)Fzvalue of '%s' under %s is Falsezvalue of '%s' under %s is %sc             s   s   | ]
}|V  qd S )Nr   )r/   cr   r   r   r0   V  s    z#Model.satisfiers.<locals>.<genexpr>z%s is not free in %s)r-   r   r   Zfreer&   rS   ry   r9   r   r   rQ   r8   r   )rH   r   Zvarexr|   r   ZnestingZspacerindentZ
candidatesrw   r   r   Zlowtracerh   resultr   r   r   
satisfiers  sB    



zModel.satisfiers)N)N)F)Nr   )r   r   r   rZ   rE   r   rN   r   r   r   r   r   r   r   r   r}     s   


E
r}      c             C   s   t dddgatg atttattat  tdt	  td tdt	  td t  tdt tdt	  dd	d
ddddddddddddddg}x>|D ]6}| rt  t
|t|  qtd|t
|tf  qW dS )z!Example of a propositional model.)PT)QT)RF*zPropositional Formulas Demoz7(Propositional constants treated as nullary predicates)z
Model m1:
z(P & Q)z(P & R)z- Pz- Rz- - Pz	- (P & R)z(P | R)z(R | P)z(R | R)z	(- P | R)z	(P | - P)z(P -> Q)z(P -> R)z(R -> P)z	(P <-> P)z	(R <-> R)z	(P <-> R)zThe value of '%s' is: %sN)rA   Zval1r8   Zdom1r}   Zm1rs   g1r&   multr   )r   Z	sentencesZsentr   r   r   propdemof  sD    


r   Fc       
      C   s  ddddt ddgfdt dd	gfd
t dgfdt ddddgfgattatjatttattddga	| st
  t
dt  t
d t
dt  t
dddt t
dt	 dddddddg}dd |D }t
  xL|D ]D}yt
d |t|t	f  W q tk
r   t
d!|  Y qX qW d"d#d$d%g}xx|D ]p\}}y>tt|t	}td&d' |D }	t
d(|||	|kf  W n& tk
r   t
d)||f  Y nX q4W d*S )+zExample of a first-order model.)adamb1)Zbettyr   )Zfidod1Zgirlr   g2boyr   b2Zdogr   love)r   r   )r   r   )r   r   )r   r   )xr   )yr   r   zModels Demoz
Model m2:
z--------------
zVariable assignment = r   walksr   r   zc             S   s   g | ]}t |qS r   )r
   rY   )r/   er   r   r   rO     s    zfolmodel.<locals>.<listcomp>z&The interpretation of '%s' in m2 is %sz-The interpretation of '%s' in m2 is Undefined)r   r   )r   )r   )r   )r   r   )r   )r   r   c             s   s    | ]}t t|tV  qd S )N)m2r   r
   rY   r   )r/   r   r   r   r   r0     s    zfolmodel.<locals>.<genexpr>z%s(%s) evaluates to %sz%s(%s) evaluates to UndefinedN)r8   Zv2rA   Zval2rS   Zdom2r}   r   rs   r   r&   r   r   r   r
   rY   r.   )
quietr   ZexprsZparsed_exprsr   ZapplicationsZfunr)   r   Zargsvalr   r   r   folmodel  sN    


r   c             C   s   t dd t  tdt  td tdt  ddddd	d
ddddddddddddg}x@|D ]8}t  | r~t|t|  q^td|t|tf  q^W dS )zF
    Interpretation of closed expressions in a first-order model.
    T)r   r   zFOL Formulas Demozlove (adam, betty)z(adam = mia)z\x. (boy(x) | girl(x))z\x. boy(x)(adam)z\x y. love(x, y)z\x y. love(x, y)(adam)(betty)z\x y. love(x, y)(adam, betty)z\x y. (boy(x) & love(x, y))z#\x. exists y. (boy(x) & love(x, y))zexists z1. boy(z1)z!exists x. (boy(x) &  -(x = adam))z&exists x. (boy(x) & all y. love(y, x))zall x. (boy(x) | girl(x))z1all x. (girl(x) -> exists y. boy(y) & love(x, y))z3exists x. (boy(x) & all y. (girl(y) -> love(y, x)))z3exists x. (boy(x) & all y. (girl(y) -> love(x, y)))zall x. (dog(x) -> - girl(x))z-exists x. exists y. (love(x, y) & love(x, y))zThe value of '%s' is: %sN)r   r&   r   r   r{   r   r   )r   formulasfmlar   r   r   foldemo  s8    

r   c             C   s   t   t dt  t d t dt  tdd ddddd	d
dddddddddddddg}| rft t x|D ]}t | t| qlW dd |D }x0|D ](}t  t d|t|dt| f  qW dS )z5Satisfiers of an open formula in a first order model.r   zSatisfiers DemoT)r   zboy(x)z(x = x)z(boy(x) | girl(x))z(boy(x) & girl(x))zlove(adam, x)zlove(x, adam)z-(x = adam)zexists z22. love(x, z22)zexists y. love(y, x)zall y. (girl(y) -> love(x, y))zall y. (girl(y) -> love(y, x))z)all y. (girl(y) -> (boy(x) & love(y, x)))z)(boy(x) & all y. (girl(y) -> love(x, y)))z)(boy(x) & all y. (girl(y) -> love(y, x)))z+(boy(x) & exists y. (girl(y) & love(y, x)))z(girl(x) -> dog(x))zall y. (dog(y) -> (x = y))z&exists y. (love(adam, y) & love(y, x))c             S   s   g | ]}t |qS r   )r
   rY   )r/   r   r   r   r   rO   &  s    zsatdemo.<locals>.<listcomp>zThe satisfiers of '%s' are: %sr   N)	r&   r   r   r   r
   rY   r   r{   r   )r   r   r   r   pr   r   r   satdemo  sB    


r   c             C   sV   t tttd}y||  |d W n0 tk
rP   x|D ]} ||  |d q6W Y nX dS )aO  
    Run exists demos.

     - num = 1: propositional logic demo
     - num = 2: first order model demo (only if trace is set)
     - num = 3: first order sentences demo
     - num = 4: satisfaction of open formulas demo
     - any other value: run all the demos

    :param trace: trace = 1, or trace = 2 for more verbose tracing
    )r^      r      )r   N)r   r   r   r   KeyError)Znumr   Zdemosr   r   r   demo-  s    
r   __main__r   )r   )N)N)FN)N)N)r   N):rZ   Z
__future__r   r   Zpprintr   r"   rG   rer    Zsixr   Znltk.decoratorsr   Znltk.compatr   Znltk.sem.logicr   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   	Exceptionr   r   r   r7   r>   r@   r#   rA   compilera   rf   VERBOSErd   rj   rW   rs   objectr}   r   r   r   r   r   r   r   r   r   r   r   <module>   sN   DB

#
  ]
1
<
,
.

