
    nie                        % S SK r S SKrS SKrS SKrS SKrS SKrS SKr	S SK
r
S SKJrJrJrJrJr  S SKJr  S SKJr  S SKJr  S SKJr  S SKJs  Js  Jr  S SKJs  Js  Jr  S SKJs  Js  J r!  S SK"Js  J#s  J$s  J%r&  S SK'Js  J#s  J$s  J(r)  S SK*J+r+  S SK,J-r-  S S	K.J/r/  S S
K0J1r1  S SK2Js  J#s  J$s  J3r4  S SK5Js  J#s  J$s  J6r7  S SK8Js  J#s  J$s  J9r:  S SK;J<r<  \ Rz                  R}                  S5      b  S SK?J@r@  S SKAJBrB  OSr@SrB\C" S5         " S S5      rDSqE\\R                     \GS'   SqH\\R                  R                     \GS'   SqJ\\K   \GS'   SqL\\R                  R                     \GS'   SqM\\R                  R                     \GS'   SqN\\R                  R                     \GS'   SqO\\R                  R                     \GS'   SqP\\R                  R                     \GS'   SqQ\\R                  R                     \GS'   SqR\\R                  R                     \GS'   SqS\\R                  R                     \GS'   SqT\\R                  R                     \GS'   / qU/ qVSqWSqX\\   \GS'   \" 5       rY\D" 5       rZS  r[S! r\S" r]S# r^S$\_S%S4S& jr`S'\R                  S%S4S( jraS$\_S%S4S) jrbS*\_S+\_S%S4S, jrcS-\-S%S4S. jrdSLS/\_S0\eS%S4S1 jjrfS2\+S%S4S3 jrgS4\S%S4S5 jrhS4\S%S4S6 jriSMS8\jS9\jS:\kS;\\1   S<\eS=\e4S> jjrlS? rmS@ rnSNSA\_4SB jjroS%\\R                  \R                  4   4SC jrq\:R                  " S SD5      SES74SF\\_   SG\:R                  SH\_SI\e4SJ jjrt\:R                  " S SD5      SES74SF\\_   SG\:R                  SH\_SI\e4SK jjrug)O    N)ListTypeCallableTupleOptional)Output)Filter)Program)GraphmlParser)Fact)Rule)	Threshold)Query)reorder_clausestorch)LogicIntegratedClassifier)ModelInterfaceOptionsz5torch is not installed, model integration is disabledc                   0   \ rS rSrS rS r\S\4S j5       r\S\4S j5       r	\S\
4S j5       r\S\4S j5       r\S\4S	 j5       r\S\4S
 j5       r\S\4S j5       r\S\4S j5       r\S\4S j5       r\S\4S j5       r\S\4S j5       r\S\4S j5       r\S\4S j5       r\S\4S j5       r\S\4S j5       r\S\
4S j5       r\S\4S j5       r\S\4S j5       r\R6                  S\SS4S j5       r\	R6                  S\SS4S j5       r	\R6                  S\
SS4S j5       r\R6                  S\SS4S j5       r\R6                  S\SS4S j5       r\R6                  S\SS4S j5       r\R6                  S\SS4S  j5       r\R6                  S\SS4S! j5       r\R6                  S\SS4S" j5       r\R6                  S\SS4S# j5       r\R6                  S\SS4S$ j5       r\R6                  S\SS4S% j5       r\R6                  S\SS4S& j5       r\R6                  S\SS4S' j5       r\R6                  S\SS4S( j5       r\R6                  S\
SS4S) j5       r\R6                  S\SS4S* j5       r\R6                  S\SS4S+ j5       rS,rg)-	_Settings)   c                     S U l         S U l        S U l        S U l        S U l        S U l        S U l        S U l        S U l        S U l	        S U l
        S U l        S U l        S U l        S U l        S U l        S U l        S U l        U R%                  5         g )N)_Settings__verbose_Settings__output_to_file_Settings__output_file_name"_Settings__graph_attribute_parsing!_Settings__abort_on_inconsistency_Settings__memory_profile_Settings__reverse_digraph_Settings__atom_trace)_Settings__save_graph_attributes_to_trace_Settings__canonical_Settings__persistent_Settings__inconsistency_check_Settings__static_graph_facts'_Settings__store_interpretation_changes_Settings__parallel_computing_Settings__update_mode_Settings__allow_ground_rules_Settings__fp_versionresetselfs    K/home/james-whalen/.local/lib/python3.13/site-packages/pyreason/pyreason.py__init___Settings.__init__*   s     $"&)-&(,% $!% 04- %)"$(!.2+$(!!$(! 

    c                     SU l         SU l        SU l        SU l        SU l        SU l        SU l        SU l        SU l        SU l	        SU l
        SU l        SU l        SU l        SU l        SU l        SU l        SU l        g )NTFpyreason_outputintersection)r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r+   s    r-   r*   _Settings.reset?   s     %"3)-&(-% %!&!05- !%)"$(!.2+$)!+$)!!r0   returnc                     U R                   $ )zJReturns whether verbose mode is on or not. Default is True

:return: bool
)r   r+   s    r-   verbose_Settings.verboseS   s     ~~r0   c                     U R                   $ )z^Returns whether output is going to be printed to file or not. Default is False

:return: bool
)r   r+   s    r-   output_to_file_Settings.output_to_file[        $$$r0   c                     U R                   $ )zReturns whether name of the file output will be saved in. Only applicable if `output_to_file` is true. Default is pyreason_output

:return: str
)r   r+   s    r-   output_file_name_Settings.output_file_namec   s     &&&r0   c                     U R                   $ )z[Returns whether graph will be parsed for attributes or not. Default is True

:return: bool
)r   r+   s    r-   graph_attribute_parsing!_Settings.graph_attribute_parsingk   s     ---r0   c                     U R                   $ )zReturns whether program will abort when it encounters an inconsistency in the interpretation or not. Default is False

:return: bool
)r   r+   s    r-   abort_on_inconsistency _Settings.abort_on_inconsistencys   s     ,,,r0   c                     U R                   $ )zbReturns whether program will profile maximum memory usage or not. Default is False

:return: bool
)r   r+   s    r-   memory_profile_Settings.memory_profile{   r<   r0   c                     U R                   $ )zReturns whether graph will be reversed or not.
If graph is reversed, an edge a->b will become b->a. Default is False

:return: bool
)r   r+   s    r-   reverse_digraph_Settings.reverse_digraph   s     %%%r0   c                     U R                   $ )zReturns whether to keep track of all atoms that are responsible for the firing of rules or not.
NOTE: Turning this on may increase memory usage. Default is False

:return: bool
)r   r+   s    r-   
atom_trace_Settings.atom_trace           r0   c                     U R                   $ )zReturns whether to save the graph attribute facts to the rule trace. Graphs are large and turning this on can result in more memory usage.
NOTE: Turning this on may increase memory usage. Default is False

:return: bool
)r    r+   s    r-   save_graph_attributes_to_trace(_Settings.save_graph_attributes_to_trace   s     444r0   c                     U R                   $ )zDEPRECATED, use persistent instead
Returns whether the interpretation is canonical or non-canonical. Default is False

:return: bool
r"   r+   s    r-   	canonical_Settings.canonical   rO   r0   c                     U R                   $ )z{Returns whether the interpretation is persistent (Does not reset bounds at each timestep). Default is False

:return: bool
rT   r+   s    r-   
persistent_Settings.persistent           r0   c                     U R                   $ )zjReturns whether to check for inconsistencies in the interpretation or not. Default is True

:return: bool
)r#   r+   s    r-   inconsistency_check_Settings.inconsistency_check   s     )))r0   c                     U R                   $ )zRReturns whether to make graph facts static or not. Default is True

:return: bool
)r$   r+   s    r-   static_graph_facts_Settings.static_graph_facts        (((r0   c                     U R                   $ )zReturns whether to keep track of changes that occur in the interpretation. You will not be able to view
interpretation results after reasoning. Default is True

:return: bool
)r%   r+   s    r-   store_interpretation_changes&_Settings.store_interpretation_changes   s     222r0   c                     U R                   $ )zReturns whether to use multiple CPU cores for inference. This will disable cacheing and pyreason will have
to be re-compiled at each run - but after compilation it will be faster. Default is False

:return: bool
)r&   r+   s    r-   parallel_computing_Settings.parallel_computing   s     (((r0   c                     U R                   $ )zrReturns the way interpretations are going to be updated. This could be "intersection" or "override"

:return: str
)r'   r+   s    r-   update_mode_Settings.update_mode   s     !!!r0   c                     U R                   $ )zTReturns whether rules can have ground atoms or not. Default is False

:return: bool
)r(   r+   s    r-   allow_ground_rules_Settings.allow_ground_rules   ra   r0   c                     U R                   $ )zoReturns whether we are using the fixed point version or the optimized version. Default is false

:return: bool
)r)   r+   s    r-   
fp_version_Settings.fp_version   rZ   r0   valueNc                 P    [        U[        5      (       d  [        S5      eXl        g)zoSet verbose mode. Default is True

:param value: verbose or not
:raises TypeError: If not boolean, raise error
value has to be a boolN)
isinstancebool	TypeErrorr   r,   rq   s     r-   r7   r8      s"     %&&455"Nr0   c                 P    [        U[        5      (       d  [        S5      eXl        g)zSet whether to put all output into a file. Default file name is `pyreason_output` and can be changed
with `output_file_name`. Default is False

:param value: whether to save to file or not
:raises TypeError: If not boolean, raise error
rs   N)rt   ru   rv   r   rw   s     r-   r:   r;      s#     %&&455$)!r0   	file_namec                 P    [        U[        5      (       d  [        S5      eXl        g)zSet output file name if `output_to_file` is true. Default is `pyreason_output`

:param file_name: File name
:raises TypeError: If not string raise error
zfile_name has to be a stringN)rt   strrv   r   )r,   ry   s     r-   r>   r?     s#     )S)):;;&/#r0   c                 P    [        U[        5      (       d  [        S5      eXl        g)zWhether to parse graphml file for attributes. Default is True

:param value: Whether to parse graphml or not
:raises TypeError: If not bool raise error
rs   N)rt   ru   rv   r   rw   s     r-   rA   rB     s#     %&&455-2*r0   c                 P    [        U[        5      (       d  [        S5      eXl        g)zWhether to abort program if inconsistency is found. Default is False

:param value: Whether to abort on inconsistency or not
:raises TypeError: If not bool raise error
rs   N)rt   ru   rv   r   rw   s     r-   rD   rE     s#     %&&455,1)r0   c                 P    [        U[        5      (       d  [        S5      eXl        g)zWhether to profile the program's memory usage. Default is False

:param value: Whether to profile program's memory usage or not
:raises TypeError: If not bool raise error
rs   N)rt   ru   rv   r   rw   s     r-   rG   rH   &  s#     %&&455$)!r0   c                 P    [        U[        5      (       d  [        S5      eXl        g)zWhether to reverse the digraph. if the graphml contains an edge: a->b
setting reverse as true will make the edge b->a. Default is False

:param value: Whether to reverse graphml edges or not
:raises TypeError: If not bool raise error
rs   N)rt   ru   rv   r   rw   s     r-   rJ   rK   2  s#     %&&455%*"r0   c                 P    [        U[        5      (       d  [        S5      eXl        g)zWhether to save all atoms that were responsible for the firing of a rule.
NOTE: this can be very memory heavy. Default is False

:param value: Whether to save all atoms or not
:raises TypeError: If not bool raise error
rs   N)rt   ru   rv   r   rw   s     r-   rM   rN   ?  s#     %&&455 %r0   c                 P    [        U[        5      (       d  [        S5      eXl        g)a  Whether to save all graph attribute facts. Graphs are large so turning this on can be memory heavy
NOTE: this can be very memory heavy. Default is False

:param value: Whether to save all graph attribute facts in the trace or not
:raises TypeError: If not bool raise error
rs   N)rt   ru   rv   r    rw   s     r-   rQ   rR   L  s#     %&&455491r0   c                 P    [        U[        5      (       d  [        S5      eXl        g)zWhether the interpretation should be canonical where bounds are reset at each timestep or not

:param value: Whether to reset all bounds at each timestep (non-canonical) or not (canonical)
:raises TypeError: If not bool raise error
rs   Nrt   ru   rv   r"   rw   s     r-   rU   rV   Y  #     %&&455 %r0   c                 P    [        U[        5      (       d  [        S5      eXl        g)zWhether the interpretation should be canonical where bounds are reset at each timestep or not

:param value: Whether to reset all bounds at each timestep (non-persistent) or (persistent)
:raises TypeError: If not bool raise error
rs   Nr   rw   s     r-   rX   rY   e  r   r0   c                 P    [        U[        5      (       d  [        S5      eXl        g)zWhether to check for inconsistencies in the interpretation or not

:param value: Whether to check for inconsistencies or not
:raises TypeError: If not bool raise error
rs   N)rt   ru   rv   r#   rw   s     r-   r\   r]   q  s#     %&&455).&r0   c                 P    [        U[        5      (       d  [        S5      eXl        g)zWhether to make graphml attribute facts static or not

:param value: Whether to make graphml facts static or not
:raises TypeError: If not bool raise error
rs   N)rt   ru   rv   r$   rw   s     r-   r_   r`   }  #     %&&455(-%r0   c                 P    [        U[        5      (       d  [        S5      eXl        g)zWhether to keep track of changes that occur to the interpretation. You will not be able to view interpretation
results after reasoning.

:param value: Whether to make graphml facts static or not
:raises TypeError: If not bool raise error
rs   N)rt   ru   rv   r%   rw   s     r-   rc   rd     s#     %&&45527/r0   c                 P    [        U[        5      (       d  [        S5      eXl        g)a?  Whether to use multiple CPU cores for inference. This will disable cacheing and pyreason will have
to be re-compiled at each run - but after compilation it will be faster. Default is False

:param value: Whether to make inference run on parallel hardware (multiple CPU cores)
:raises TypeError: If not bool raise error
rs   N)rt   ru   rv   r&   rw   s     r-   rf   rg     s#     %&&455(-%r0   c                 P    [        U[        5      (       d  [        S5      eXl        g)zThe way interpretations are going to be updated. This could be "intersection" or "override". Default is
 'intersection'

:param value: "intersection" or "override"
:raises TypeError: If not str raise error
zvalue has to be a strN)rt   r{   rv   r'   rw   s     r-   ri   rj     s#     %%%344!&r0   c                 P    [        U[        5      (       d  [        S5      eXl        g)zAllow ground atoms to be used in rules when possible. Default is False

:param value: Whether to allow ground atoms or not
:raises TypeError: If not bool raise error
rs   N)rt   ru   rv   r(   rw   s     r-   rl   rm     r   r0   c                 P    [        U[        5      (       d  [        S5      eXl        g)zSet the fixed point or optimized version. Default is False

:param value: Whether to use the fixed point version or the optimized version
:raises TypeError: If not bool raise error
rs   N)rt   ru   rv   r)   rw   s     r-   ro   rp     r   r0   )__abort_on_inconsistency__allow_ground_rules__atom_trace__canonical__fp_version__graph_attribute_parsing__inconsistency_check__memory_profile__output_file_name__output_to_file__parallel_computing__persistent__reverse_digraph __save_graph_attributes_to_trace__static_graph_facts__store_interpretation_changes__update_mode	__verbose)__name__
__module____qualname____firstlineno__r.   r*   propertyru   r7   r:   r{   r>   rA   rD   rG   rJ   rM   rQ   rU   rX   r\   r_   rc   rf   ri   rl   ro   setter__static_attributes__ r0   r-   r   r   )   s   *"(    % % % '# ' ' . . . - - - % % % & & & !D ! ! 5 5 5 !4 ! ! !D ! ! *T * * )D ) ) 3d 3 3 )D ) ) "S " " )D ) ) !D ! ! ^^	#T 	#d 	# 	# 
*D 
*T 
* 
* 	0# 	0$ 	0 	0 ##	3T 	3d 	3 $	3 ""	2D 	2T 	2 #	2 	*D 	*T 	* 	* 
+T 
+d 
+ 
+ 
& 
& 
& 
& $**
:D 
:T 
: +
: 	&t 	& 	& 	& 	& 	& 	& 	& 	/ 	/$ 	/  	/ 	. 	. 	. 	. "((
8$ 
84 
8 )
8 
. 
. 
. 
. 
' 
' 
' 
' 	. 	. 	. 	. 	& 	& 	& 	&r0   r   __graph__rules__clause_maps__node_facts__edge_facts__ipl__specific_node_labels__specific_edge_labels__non_fluent_graph_facts_node__non_fluent_graph_facts_edge__specific_graph_node_labels__specific_graph_edge_labels 	__programc                      Sq Sq[        b  [        R                  5         Sq[        b  [        R                  5         [        5         g)ztResets certain variables to None to be able to do pr.reason() multiple times in a program
without memory blowing up
N)r   r   r   reset_factsr   reset_graphreset_rulesr   r0   r-   r*   r*     s@     LL G Mr0   c                      [         $ )z
Returns the rules
)r   r   r0   r-   	get_rulesr     s	     Nr0   c                  H    Sq / q/ q[        b  [        R	                  5         gg)z
Resets rules to none
N)r   __annotation_functions__head_functionsr   r   r   r0   r-   r   r     s,    
 G r0   c                  ,    [         R                  5         g)z
Resets settings to default
N)settingsr*   r   r0   r-   reset_settingsr   
  s     NNr0   pathr5   c           	         [         R                  U [        R                  5      q[        R
                  (       a)  [         R                  [        R                  5      u  qq	q
qg[        R                  R                  R                  [         R"                  5      q[        R                  R                  R                  [$        R"                  5      q	[        R                  R&                  R)                  [*        R,                  [        R.                  R1                  [        R.                  R2                  5      S9q
[        R                  R&                  R)                  [*        R,                  [        R.                  R1                  [        R.                  R5                  [        R.                  R2                  [        R.                  R2                  45      5      S9qg)zXLoads graph from GraphMl file path into program

:param path: Path for the GraphMl file
key_type
value_typeN)__graphml_parserparse_graphr   rJ   r   rA   parse_graph_attributesr_   r   r   r   r   numbatypedr   
empty_list	fact_node	fact_type	fact_edgeDictemptylabel
label_typetypesListTypestringr   r   s    r-   load_graphmlr     s    **41I1IJG '' DT  Dk  Dk  lt  lG  lG  DH  	A%'DFb  eA(-(8(8(C(CIDWDW(X%(-(8(8(C(CIDWDW(X%',{{'7'7'='=uGWGWdidododxdxy~  zE  zE  zL  zL  eM'=  (N$',{{'7'7'='=uGWGWdidododxdxy~  zE  zE  zK  zK  MR  MX  MX  M_  M_  af  al  al  as  as  Lt  zu  ev'=  (w$r0   graphc           	         [         R                  U 5      q[        R                  (       a)  [         R                  [        R                  5      u  qqq	q
g[        R                  R                  R                  [        R                   5      q[        R                  R                  R                  ["        R                   5      q[        R                  R$                  R'                  [(        R*                  [        R,                  R/                  [        R,                  R0                  5      S9q	[        R                  R$                  R'                  [(        R*                  [        R,                  R/                  [        R,                  R3                  [        R,                  R0                  [        R,                  R0                  45      5      S9q
g)zLoad a networkx DiGraph into pyreason

:param graph: Networkx DiGraph object to load into pyreason
:type graph: nx.DiGraph
:return: None
r   N)r   
load_graphr   r   rA   r   r_   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r   s    r-   r   r   &  s    ))%0G '' DT  Dk  Dk  lt  lG  lG  DH  	A%'DFb  eA(-(8(8(C(CIDWDW(X%(-(8(8(C(CIDWDW(X%',{{'7'7'='=uGWGWdidododxdxy~  zE  zE  zL  zL  eM'=  (N$',{{'7'7'='=uGWGWdidododxdxy~  zE  zE  zK  zK  MR  MX  MX  M_  M_  af  al  al  as  as  Lt  zu  ev'=  (w$r0   c                 0    [         R                  " U 5      qg)zSLoad IPL from YAML file path into program

:param path: Path for the YAML IPL file
N)yaml_parser	parse_iplr   r   s    r-    load_inconsistent_predicate_listr   <  s     !!$'Er0   pred1pred2c                 X   [         cd  [        R                  R                  R	                  [        R
                  R                  [        R                  [        R                  45      5      q [         R                  [        R                  " U 5      [        R                  " U5      45        g)zAdd an inconsistent predicate pair to the IPL

:param pred1: First predicate in the inconsistent pair
:param pred2: Second predicate in the inconsistent pair
N)r   r   r   r   r   r   r   r   r   appendLabel)r   r   s     r-   add_inconsistent_predicater   E  sg     }  ++EKK,=,=u?O?OQVQaQa>b,cd	LL%++e$ekk%&89:r0   pr_rulec                 J   [         c7  [        R                  R                  R	                  [
        R                  5      q U R
                  R                  5       c+  U R
                  R                  S[        [         5       35        [         R                  U R
                  5        g)z_Add a rule to pyreason from text format. This format is not as modular as the YAML format.
    Nrule_)r   r   r   r   r   rule	rule_typeget_rule_nameset_rule_namelenr   )r   s    r-   add_ruler   Q  si     ++""--dnn= ||!!#+""U3w<.#9:NN7<< r0   	file_pathinfer_edgesc           	         [        U S5       nU Vs/ s HA  o3R                  5       S:w  d  M  UR                  5       S   S:w  d  M1  UR                  5       PMC     nnSSS5        [        c  SO[        [        5      n[	        W5       H   u  pg[        [        USXe-    3U5      5        M"     gs  snf ! , (       d  f       N[= f)a)  Add a set of rules from a text file

:param file_path: Path to the text file containing rules
:type file_path: str
:param infer_edges: Whether to infer edges on these rules if an edge doesn't exist between head variables and the body of the rule is satisfied
:type infer_edges: bool
:return: None
rr   r   #Nr   )openrstripr   r   	enumerater   r   )r   r   filelinerulesrule_offsetir   s           r-   add_rules_from_filer   a  s     
i	+/c44;;=B3F4;;=YZK[_bKb4c 
 !CLK% a50+>? ! d 
	s'   B1B,B,B,B1,B11
B?pyreason_factc           	         [         c7  [        R                  R                  R	                  [
        R                  5      q [        c7  [        R                  R                  R	                  [        R                  5      qU R                  S:X  a  U R                  c'  S[        [         5      [        [        5      -    3U l
        [
        R                  " U R                  U R                  U R                  U R                  U R                   U R"                  U R$                  5      n[         R'                  U5        gU R                  c'  S[        [         5      [        [        5      -    3U l
        [        R                  " U R                  U R                  U R                  U R                  U R                   U R"                  U R$                  5      n[        R'                  U5        g)zrAdd a PyReason fact to the program.

:param pyreason_fact: PyReason fact created using pr.Fact(...)
:return: None
Nnodefact_)r   r   r   r   r   r   r   r   r   typenamer   r   	componentpredbound
start_timeend_timestaticr   )r   fs     r-   add_factr
  r  s    {{''2293F3FG{{''2293F3FGV#%#(\):3|;L)L(M!NMNN=--}/F/FHZHZ\i\o\oq~  rJ  rJ  LY  Lb  Lb  dq  dx  dx  yA%#(\):3|;L)L(M!NMNN=--}/F/FHZHZ\i\o\oq~  rJ  rJ  LY  Lb  Lb  dq  dx  dx  yAr0   functionc                 .    [         R                  U 5        g)a!  Function to add annotation functions to PyReason. The added functions can be used in rules

:param function: Function to be added. This has to be under a numba `njit` decorator. function has signature: two parameters as input -- annotations, weights
:type function: Callable
:return: None
N)r   r   r  s    r-   add_annotation_functionr    s     !!(+r0   c                 .    [         R                  U 5        g)a  Function to add head functions to PyReason. The added functions can be used in rules

:param function: Function to be added. This has to be under a numba `njit` decorator. function has signature: one parameter as input -- annotations
:type function: Callable
:return: None
N)r   r   r  s    r-   add_head_functionr    s     H%r0   T	timestepsconvergence_thresholdconvergence_bound_thresholdqueriesagainrestartc                 z   [         R                  " S5      q[        R                  (       a.  [        S[        R                   S[         S3S5      [        l        U(       a  [        ck  [        R                  (       aG  [        R                  " SS9n[        R                  " [        XX#/4SSS9u  px[        S	Xv-
   S
35        U$ [        XX#5      n U$ [        R                  (       aG  [        R                  " SS9n[        R                  " [        XX/4SSS9u  px[        S	Xv-
   S
35        U$ [        XX5      nU$ )a  Function to start the main reasoning process. Graph and rules must already be loaded.

:param timesteps: Max number of timesteps to run. -1 specifies run till convergence. If reasoning again, this is the number of timesteps to reason for extra (no zero timestep), defaults to -1
:param convergence_threshold: Maximum number of interpretations that have changed between timesteps or fixed point operations until considered convergent. Program will end at convergence. -1 => no changes, perfect convergence, defaults to -1
:param convergence_bound_threshold: Maximum change in any interpretation (bounds) between timesteps or fixed point operations until considered convergent, defaults to -1
:param queries: A list of PyReason query objects that can be used to filter the ruleset based on the query. Default is None
:param again: Whether to reason again on an existing interpretation, defaults to False
:param restart: Whether to restart the program time from 0 when reasoning again, defaults to True
:return: The final interpretation after reasoning.
z%Y%m%d-%H%M%S./_.txtaT)	max_usage)r  retvalz
Program used z MB of memory)timestrftime__timestampr   r:   r   r>   sysstdoutr   rG   mpmemory_usage_reasonprint_reason_again)	r  r  r  r  r  r  	start_mem	mem_usageinterps	            r-   reasonr+    s@    --0KBx889;-tLcR
I%""$7I "9]x  ;C  1D  PT  ]a  !bIOI$7#8FG M Y?ZdF M ""$7I "Uj  AI  1J  VZ  cg  !hIOI$7#8FG M #97LjFMr0   c                    [         R                  (       a.  [        S[         R                   S[         S3S5      [
        l        [        cI  [        [        R                  " 5       5        [         R                  (       a  [        R                  " S5        [        c  [        S5      e[         c7  ["        R$                  R&                  R)                  [*        R,                  5      q[.        c7  ["        R$                  R&                  R)                  [0        R,                  5      q[2        cd  ["        R$                  R&                  R)                  ["        R4                  R7                  [8        R:                  [8        R:                  45      5      q["        R$                  R<                  R?                  [8        R:                  ["        R4                  RA                  ["        R4                  RB                  5      S9q"["        R$                  R<                  R?                  [8        R:                  ["        R4                  RA                  ["        R4                  R7                  ["        R4                  RB                  ["        R4                  RB                  45      5      S9q#[H        RK                  5        H2  u  pEU[D        ;   a  [D        U   RM                  U5        M)  U[D        U'   M4     [N        RK                  5        H2  u  pFU[F        ;   a  [F        U   RM                  U5        M)  U[F        U'   M4     ["        R$                  R&                  R)                  [*        R,                  5      n["        R$                  R&                  R)                  [0        R,                  5      nURM                  ["        R$                  R'                  [         5      5        URM                  ["        R$                  R'                  [.        5      5        URM                  [P        5        URM                  [R        5        [         RT                  (       d  S[         l+        [Y        [Z        5      n	[Y        [\        5      n
[         R                  (       a  [_        S	5        Ub  [`        Rb                  " U[        5      q[         VVs0 s HD  oRe                  5       [g        [i        URk                  5       5      5       Vs0 s H  oU_M     sn_MF     snnq6[i        [        Rn                  5      [i        [        Rp                  5      :  a  [         R                  (       a  [_        S
5        [        Rs                  5       n["        R$                  R&                  R)                  [t        Rv                  5      q[y        U5       H=  u  p[{        U5      u  n[l        URe                  5       '   [        R}                  U5        M?     [        [        Xx[        [2        X[         R                  [         RV                  [         R                  [         R                  [         R                  [         RT                  [         R                  [         R                  [         R                  [         R                  5      qH[D        [        lI        [F        [        lJ        [        R                  XU[         R                  5      nS qS qU$ s  snf s  snnf )Nr  r  r  r  zNGraph not loaded. Use `load_graph` to load the graphml file. Using empty graphz;There are no rules, use `add_rule` or `add_rules_from_file`r   Fz Filtering rules based on queriesz=Optimizing rules by moving node clauses ahead of edge clauses)Lr   r:   r   r>   r   r!  r"  r   r   nxDiGraphr7   warningswarnr   	Exceptionr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   itemsextendr   r   r   rc   rM   tupler   r   r&  ruleset_filterfilter_rulesetr   ranger   get_clausesr   edgesnodescopyr   r   r   r   r   r
   rJ   rQ   rX   r\   rf   ri   rl   ro   r   specific_node_labelsspecific_edge_labelsr+  )r  r  r  r  
label_namer:  r9  all_node_factsall_edge_factsannotation_functionshead_functionsr   r   __rules_copyinterpretations                  r-   r%  r%    sm    Bx889;-tLcR
 2::< MMjkUVV {{''2293F3FG{{''2293F3FG}  ++EKK,=,=u?O?OQVQaQa>b,cd #[[--33U=M=MZ_ZeZeZnZnotozoz  pB  pB  [C3  D"[[--33U=M=MZ_ZeZeZnZnotozoz  pA  pA  CH  CN  CN  CU  CU  W\  Wb  Wb  Wi  Wi  Bj  pk  [l3  m9??A
//":.55e<16":.	 B :??A
//":.55e<16":.	 B [[%%001D1DEN[[%%001D1DEN%++**<89%++**<897878 00# !!78+,N 01 //A ^ee]dXY__&uS=Q7R(S7R!A7R(SS]deM
7==C..QR||~++""--dnn=l+DA2A!2D/A}Q__./NN1 ,
 %Qew  xP  xP  RZ  Re  Re  go  gN  gN  PX  Pc  Pc  em  eA  eA  CK  Ch  Ch  jr  jE  jE  GO  G[  G[  ]e  ]x  ]x  zB  zM  zM  NI%;I"%;I" %%iHcemeueuvN LL- )Tes   /8[('[#3[(#[(c           	         [         c   S5       e[        R                  R                  R	                  [
        R                  5      n[        R                  R                  R	                  [        R                  5      nUR                  [        R                  R                  [        5      5        UR                  [        R                  R                  [        5      5        [         R                  XX#XE[        R                  5      nU$ )Nz;To run `reason_again` you need to have reasoned once before)r   r   r   r   r   r   r   r   r3  r   r   reason_againr   r7   )r  r  r  r  r?  r@  rD  s          r-   r'  r'  $  s     _"__  [[%%001D1DEN[[%%001D1DEN%++**<89%++**<89 ++I@U  uC  U]  Ue  Ue  fNr0   folderc                     [         R                  (       d   S5       e[        [        [        5      nUR                  X5        g)aa  Saves the trace of the program. This includes every change that has occurred to the interpretation. If `atom_trace` was set to true
this gives us full explainability of why interpretations changed

:param interpretation: the output of `pyreason.reason()`, the final interpretation
:param folder: the folder in which to save the result, defaults to './'
Gstore interpretation changes setting is off, turn on to save rule traceN)r   rc   r   r   r   save_rule_trace)rD  rG  outputs      r-   rJ  rJ  4  s3     00{2{{0K/F
>2r0   c                     [         R                  (       d   S5       e[        [        [        5      nUR                  U 5      $ )a  Returns the trace of the program as 2 pandas dataframes (one for nodes, one for edges).
This includes every change that has occurred to the interpretation. If `atom_trace` was set to true
this gives us full explainability of why interpretations changed

:param interpretation: the output of `pyreason.reason()`, the final interpretation
:returns two pandas dataframes (nodes, edges) representing the changes that occurred during reasoning
rI  )r   rc   r   r   r   get_rule_trace)rD  rK  s     r-   rM  rM  A  s6     00{2{{0K/F  00r0      lowerlabelsr  sort_by
descendingc                     [         R                  (       d   S5       e[        U R                  5      nUR	                  XX#U5      nU$ )a  Filters and sorts the node changes in the interpretation and returns as a list of Pandas dataframes that are easy to access

:param interpretation: the output of `pyreason.reason()`, the final interpretation
:param labels: A list of strings, labels that are in the interpretation that are to be filtered
:param bound: The bound that will filter any interpretation that is not in it. the default does not filter anything, defaults to interval.closed(0,1)
:param sort_by: String that is either 'lower' or 'upper', sorts by the lower/upper bound, defaults to 'lower'
:param descending: A bool that sorts by descending/ascending order, defaults to True
:return: A list of Pandas dataframes that contain the filtered and sorted interpretations that are easy to access
zMstore interpretation changes setting is off, turn on to filter and sort nodes)r   rc   r	   r  filter_and_sort_nodesrD  rP  r  rQ  rR  filtererfiltered_dfs          r-   rT  rT  O  M     00  B  3B  B0n))*H00YcdKr0   c                     [         R                  (       d   S5       e[        U R                  5      nUR	                  XX#U5      nU$ )a  Filters and sorts the edge changes in the interpretation and returns as a list of Pandas dataframes that are easy to access

:param interpretation: the output of `pyreason.reason()`, the final interpretation
:param labels: A list of strings, labels that are in the interpretation that are to be filtered
:param bound: The bound that will filter any interpretation that is not in it. the default does not filter anything, defaults to interval.closed(0,1)
:param sort_by: String that is either 'lower' or 'upper', sorts by the lower/upper bound, defaults to 'lower'
:param descending: A bool that sorts by descending/ascending order, defaults to True
:return: A list of Pandas dataframes that contain the filtered and sorted interpretations that are easy to access
zMstore interpretation changes setting is off, turn on to filter and sort edges)r   rc   r	   r  filter_and_sort_edgesrU  s          r-   rZ  rZ  _  rX  r0   )F)r[  r[  NFT)r  )v	importlibnetworkxr-  r   r  r!  pandaspdmemory_profilerr#  r/  typingr   r   r   r   r   pyreason.scripts.utils.outputr   pyreason.scripts.utils.filterr	    pyreason.scripts.program.programr
   %pyreason.scripts.utils.graphml_parserr   "pyreason.scripts.utils.yaml_parserscriptsutilsr   "pyreason.scripts.utils.rule_parserrule_parser%pyreason.scripts.utils.filter_rulesetr6  r5  5pyreason.scripts.numba_wrapper.numba_types.label_typenumba_wrappernumba_typesr   r   4pyreason.scripts.numba_wrapper.numba_types.rule_typer   r   pyreason.scripts.facts.factr   pyreason.scripts.rules.ruler   $pyreason.scripts.threshold.thresholdr   pyreason.scripts.query.queryr   9pyreason.scripts.numba_wrapper.numba_types.fact_node_typefact_node_typer   9pyreason.scripts.numba_wrapper.numba_types.fact_edge_typefact_edge_typer   8pyreason.scripts.numba_wrapper.numba_types.interval_typeinterval_typeinterval&pyreason.scripts.utils.reorder_clausesr   util	find_spec3pyreason.scripts.learning.classification.classifierr   /pyreason.scripts.learning.utils.model_interfacer   r&  r   r   r.  __annotations__r   r   r   dictr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r*   r   r   r   r{   r   r   r   r   r   ru   r   r
  r  r  intfloatr+  r%  r'  rJ  	DataFramerM  closedIntervalrT  rZ  r   r0   r-   <module>r     s       
    8 8 0 0 4 ? 8 8 8 8 > > E E C C , , : . M M M M K K B>>G$0]U $ 	
AB
]& ]&B !%"**	 $&*%++""	# * $x~ $+/hu{{''( /+/hu{{''( /$(x  ! (59 !1!12 959 !1!12 9<@ x(8(89 @<@ x(8(89 @;? hu{{'7'78 ?;? hu{{'7'78 ?  #	8G # ? ;*	 ws wt w(wbjj wT w,(3 (4 (	;c 	;# 	;$ 	;!d !t ! @3 @T @d @"D T 2,h ,4 ,
& 
&T 
&"c "s "^c "swx}s~ "  OS "  fj "JVr 
3C 
31eBLL",,,F&G 1 W_VeVefghiVj  zA  TX $s) HDUDU ux   OS   W_VeVefghiVj  zA  TX $s) HDUDU ux   OS r0   