
    e!hB                         d 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
 ddlmZmZmZ ddlmZmZmZmZ dd	lmZ dd
lmZ ddlmZ ddlmZ  G d de      Zy)a  
RETE algorithm implementation.

This is implemented as described by Charles L. Forgy in his original
Ph.D thesis paper_. With minor changes to allow CLIPS like matching and
a more pythonic approach.

.. _paper: http://reports-archive.adm.cs.cmu.edu/anon/scan/CMU-CS-79-forgy.pdf

    )	lru_cache)chain)Counter   )	TypeCheckFactCaptureFeatureCheck)BusNodeConflictSetNodeFeatureTesterNode)prepare_ruleextract_factsgenerate_checks	wire_rule)OR)Rule)InitialFact)Matcherc                        e Zd ZdZ fdZ ed      d        ZddZd Zd Z	e
d	        Ze
d
        Ze
d        Zd Zd Z xZS )ReteMatcherz0RETE algorithm with `experta` matcher interface.c                 b    t        |   |i | t               | _        | j	                          y)z*Create the RETE network for `self.engine`.N)super__init__r
   	root_nodebuild_network)selfargskwargs	__class__s      f/var/www/html/diagnosisapp-backend/venv/lib/python3.12/site-packages/experta/matchers/rete/__init__.pyr   zReteMatcher.__init__   s*    $)&)     r   )maxsizec                     t               }fd | j                        D ]  }||vs|j                  |        t        |      S )Nc              3      K   t        | t              r|  | j                  D ]  } |j                        E d {     y 7 wN)
isinstancer   childrennode)r(   child_get_csns     r    r*   z5ReteMatcher._get_conflict_set_nodes.<locals>._get_csn%   s>     $0
 0#EJJ///0/s   9AAA)listr   appendtuple)r   nodesr(   r*   s      @r    _get_conflict_set_nodesz#ReteMatcher._get_conflict_set_nodes!   sI    	0 T^^, 	#D5 T"	# U|r!   c                 V   |"|D ]  }| j                   j                  |        |"|D ]  }| j                   j                  |        t               }t               }| j	                         D ]7  }|j                         \  }}|j                  |       |j                  |       9 ||fS )z(Pass the given changes to the root_node.)r   removeaddr+   r/   get_activationsextend)	r   addingdeletingdeletedaddedremovedcsnc_added	c_removeds	            r    changeszReteMatcher.changes1   s    # /%%g./  *""5)* &//1 	&C!$!4!4!6GYLL!NN9%	&
 wr!   c                     | j                  | j                        }| j                  || j                        }| j	                  ||       y r%   )prepare_rulesetenginebuild_alpha_partr   build_beta_part)r   rulesetalpha_terminalss      r    r   zReteMatcher.build_networkE   s<    &&t{{3//HWo6r!   c                 8    | j                   j                          y r%   )r   reset)r   s    r    rF   zReteMatcher.resetJ   s    r!   c                 Z    | j                         D ch c]  }t        |       c}S c c}w )zs
        Given a `KnowledgeEngine`, generate a set of rules suitable for
        RETE network generation.

        )	get_rulesr   )r@   rules     r    r?   zReteMatcher.prepare_rulesetM   s&     06/?/?/ABtT"BBBs   (c           	          | j                         } | j                  t        t                            | D ci c]  }|t	        |       c}t        j                  j                               D ci c]  }|t        t        |             c}t        t        j                  j                                     fd}fd}t        | |d      }t               }|D ]  }|   D ]  }|}t        |   |d      }	|	D ]b  }
|j                  D ](  }|j                  j                  |
u s|j                  } 9 t!        |
      }|j#                  ||j$                         |}d |||<     |S c c}w c c}w )z
        Given a set of already adapted rules, build the alpha part of
        the RETE network starting at `root_node`.

        c                     t        | t              rt        d      t        |       fS t        | t              rt        d      t        |       fS t        | t
              r|    t        |       fS t        d      )z0Sort check by its type and number of times seen.infz-infzUnknown check type.)r&   r   floathashr   r	   	TypeError)check
check_ranks    r    weighted_check_sortz9ReteMatcher.build_alpha_part.<locals>.weighted_check_sorto   sg    %+ed5k22E;/ftE{33E<0"5)4;77 566r!   c                 b    d}|    D ]  }|   D ]
  }||   z  }  |t        |          z  S )z/Sort rules by the average weight of its checks.r   )len)rI   totalfactrP   rQ   fact_checks
rule_factss       r    weighted_rule_sortz8ReteMatcher.build_alpha_part.<locals>.weighted_rule_sortz   sV    E"4( /(. /EZ..E// 3z$/000r!   T)keyreverse)copyr2   r   r   r   r   from_iterablevaluessetr   r   sorteddictr'   r(   matcherr   	add_childactivate)rC   r   rI   rV   rR   rY   sorted_rulesfact_terminal_nodescurrent_nodefact_sorted_checksrP   r)   new_noderQ   rW   rX   s                @@@r    rA   zReteMatcher.build_alpha_partV   s    ,,.D'( =DDDdM$//D

 $)#6#6z7H7H7J#KM S!677 M U001C1C1EFG
		7	1 g+=tL"f ! 	9D"4( 9(%+%+ &""
 0 0E ".!6!6 0 ::--6+0::L!0 $5U#;$..x9J9JK'/0 -9#D))9	92 #"y EMs   E65E;c                     | D ]<  }t        |d   t              r|d   D ]  }t        |||        /t        |||       > y)z
        Given a set of already adapted rules, and a dictionary of
        patterns and alpha_nodes, wire up the beta part of the RETE
        network.

        r   )lhsN)r&   r   r   )rC   rD   rI   subrules       r    rB   zReteMatcher.build_beta_part   sP      	;D$q'2&#Aw BGdOAB $T:	;r!   c                 n    t               fdddj                   | j                              z  S )z8
        Generate a graphviz compatible graph.

        c           	   3     K   t        t        |             }dj                  |t        |              | j                  D ]  }| |j                  fvrcdj                  |t        t        |j
                              |j                  j                         j                  | |j                  f        |j
                        E d {     y 7 w)Nz{name} [label="{cls_name}"];)namecls_namez,{parent} -> {child} [label="{child_label}"];)parentr)   child_label)stridformatr'   callbackr(   __name__r2   )r(   ro   r)   edges	gen_edgess      r    ry   z,ReteMatcher.print_network.<locals>.gen_edges   s     r$x=D077T 8 $ $  1%..)667=v#!"UZZ.1$)NN$;$; 8> 8==
 IItU^^45$UZZ0001 1s   C
CCCzdigraph {
 %s 
}
)r_   joinr   )r   rx   ry   s    @@r    print_networkzReteMatcher.print_network   s7    
 	1$ $tyydnn%(' ( 	(r!   c                 :    ddl m}  || j                               S )Nr   )Source)graphvizr~   r|   )r   r~   s     r    show_networkzReteMatcher.show_network   s    #d((*++r!   )NN)rw   
__module____qualname____doc__r   r   r/   r=   r   rF   staticmethodr?   rA   rB   r|   r   __classcell__)r   s   @r    r   r      s~    : q  (7
 C C J# J#X ; ;(8,r!   r   N)r   	functoolsr   	itertoolsr   collectionsr   rP   r   r   r	   r.   r
   r   r   utilsr   r   r   r   expertar   experta.ruler   experta.factr   experta.abstractr   r    r!   r    <module>r      sA   	     7 7 > > J J   $ $x,' x,r!   