
    *-hL                    d   S r SSKJr  SSK7  SSK7  SSK7  SSK7  SSKJr  SSKrSSK	r	SSK
r
SSKr\R                  R                  S:  a  SSKJrJr  SS	KJr  SS
KJrJrJr  SqS r\R                  R                  S:  a  S rOS rS rS rS rS rS rS rS rS rS r GSGS jr!S r"S r#S r$S r%S r& " S S5      r'Sq(S \'4S! jr)S \'4S" jr*S \'4S# jr+S$ r,GSHS% jr-S& r.S' r/ " S( S)5      r0 " S* S+\05      r1S,\S \24S- jr3S,\1S.\1S \24S/ jr4S0\'S,\S \54S1 jr6GSGS2 jr7S3 r8S4 r9S5 r:S6 r;S7 r<S8 r= " S9 S:\15      r>S;\S \24S< jr?S= r@S0\'S,\S \>4S> jrAGSGS \>4S? jjrB " S@ SA\>5      rCGSGSB jrD " SC SD\15      rESE rFSF rGSG rHSH rISI rJSJ rK " SK SL\15      rLSM rMSN rNSO rOGSGSP jrPSQ rQGSGSR jrRSS rSST rTSU rUSV rVSW rWSX rXGSGSY jrYSZ rZS[ r[S\ r\S] r]GSIS^ jr^S_\5S;\>S \L4S` jr_GSGS_\5S \L4Sa jjr`GSGSb\54Sc jjra " Sd Se\>5      rb " Sf Sg\L5      rcS,\S \24Sh jrdS,\S \24Si jreS,\S \24Sj jrfS,\S \24Sk jrgS,\S \24Sl jrhS,\S \24Sm jriS,\S \24Sn jrjS,\S \24So jrkS,\S \24Sp jrlGSGSq jrmGSGSr jrnGSGSs jroGSGSt jrpGSGSu jrqGSJSv jrrGSGSw jrsGSGSx jrtGSGSy jruSz rvS{ rwS| rxS} ry " S~ S\L5      rzS r{S r|S r} " S S\c5      r~S rSSS/ / 4S jrSSS/ / 4S jrSSS/ / 4S jrS r " S S\>5      rS;\S \24S jr " S S\L5      rS rS \24S jrS rS rS rS rS rS rS,\S \24S jrS,\S \24S jrS,\S \24S jrS,\S \24S jrS,\S \24S jrS,\S \24S jrS,\S \24S jrS,\S \24S jrS,\S \24S jrS,\S \24S jrS,\S \24S jrS,\S \24S jrS,\S \24S jr " S S\5      r " S S\5      r " S S\5      rGSGS jrGSGS jrGSGS jrS rGSGS jrGSGS jrGSGS jrGSGS jrGSGS jrGSGS jrGSGS jrGSKS jrGSGS jrGSGS jrGSGS jrGSJS jrS rS rS rGSGS jrGSGS jr " S S\>5      rS r " S S\L5      r " S S\5      rS rS rGSLS jrS rGSGS jrGSGS jrGSGS jrGSGS jrS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS r " S S\>5      r " S S\L5      rS rS rS,\S \24S jrS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rGS  rGS rGS rGS rGS rGS rGS rGS rGS rGS	 rGS
 rGS rGS r " GS GS5      r " GS GS5      r " GS GS5      rGS r " GS GS\>5      Gr  " GS GS\L5      GrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGr " GS GS5      GrGSGGS jGr " GS GS 5      Gr " GS! GS"\05      Gr	 " GS# GS$\05      Gr
 " GS% GS&5      Gr " GS' GS(5      Gr " GS) GS*\05      Gr " GS+ GS,\05      GrS0 4GS- jGrGS. GrGS/ Gr " GS0 GS15      Gr " GS2 GS35      GrG\" G\5      GrG\" G\5      GrG\" G\5      Gr " GS4 GS5\05      GrGSMGS6 jGrGSMGS7 jGr " GS8 GS9\05      Gr " GS: GS;\>5      GrGSGGS< jGrGS= Gr  " GS> GS?\L5      Gr!GS@ Gr" " GSA GSBG\!5      Gr#GSGGSC jGr$GSD Gr% " GSE GSF5      Gr&0 Gr'GSG Gr(G\)" G\(5      Gr* " GSH GSI\05      Gr+ " GSJ GSK\05      Gr, " GSL GSM5      Gr- " GSN GSO5      Gr.GSP Gr/GSGGSQ jGr0GSGGSR jGr1GSGGSS jGr2GST Gr3GSU Gr4GSV Gr5GSW Gr6GSGGSX jGr7GSGGSY jGr8GSZ Gr9GS[ Gr:GSNGS\ jGr;GSGGS] jGr<GSGGS^ jGr=GSGGS_ jGr>GS` Gr? " GSa GSb5      Gr@GSc GrAGSGGSd jGrBGSGGSe jGrCGSGGSf jGrDGSg GrEGSh GrFGSi GrGGSj GrHGSGGSk jGrIGSGGSl jGrJGSGGSm jGrKGSn GrLGSo GrMGSp GrNGSq GrOGSr GrPGSs GrQGSt GrRGSu GrSGSv GrTGSw GrUGSx GrVGSy GrWGSGGSz jGrXGS{ GrYGS| GrZGSGGS} jGr[GS~ Gr\GS Gr]GSLGS jGr^GS Gr_GS Gr`GSLGS jGraGS GrbGS Grc " GS GS5      Grd0 0 S4GS jGre0 0 S4GS jGrfG\gGqhGSGqiGSGqjGSGGS jGrkG\l" G\mG\nG\oG\gG\p15      GrqGSGGS jGrrGSGGS jGrsGSGGS jGrtGSGGS jGruGSGGS jGrvGS Grw " GS GS\>5      GrxGSGGS jGryGSGGS jGrzGSGGS jGr{GSGGS jGr|GSGGS jGr}GSGGS jGr~GSGGS jGrGSGGS jGr " GS GS\>5      GrGS GrGS Gr " GS GS\L5      Gr " GS GS\L5      GrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGS GrGS Gr " GS GSG\5      GrGS GrGS GrGSGGS jGrGSOGS jGrGS GrGS GrGS GrGS GrGS GrGS GrGS GrGSPGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGS GrGS GrGS GrGS GrGS GrGS GrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGS GrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSPGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGr " GS GS\>5      Gr " GS GS\>5      GrGSGGS jGrGSGGS jGrGS Gr " GS GS\L5      GrGSGGS jGr " GS GS\L5      GrGSGGS jGrGS GrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGSGGS jGrGS  GrS,\S \24GS jGrS,\S \24GS jGrGSGGS jGrGSGGS jGrGSGGS jGrGS GrGS GrGS GrGS	 GrGS
 GrGS GrGS GrGS GrGS GrGSGGS jGrGS GrGS GrGS GrGS GrGS GrGS GrGS GrGS GrGS GrGS GrGSGGS jGr " GS GS\>5      GrGS Gr " GS GS\L5      GrGS  GrGS! GrGS" GrGS# GrGS$ GrGS% GrGS& Gr GS' GrGSOGS( jGrGSGGS) jGrGSGGS* jGrGSGGS+ jGrGS, GrGS- GrGS. GrGS/ Gr	GS0 Gr
GS1 GrGS2 GrGS3 GrSGqGS4 GrG\" G\5      Gr " GS5 GS65      Gr " GS7 GS85      GrSGqGS9 GrGS: GrGS; GrGS< GrGS= GrGS> GrGS? GrGS@ GrGSA GrGSB GrGSC GrG\ " G\5      Gr!G\"" G\5      Gr#G\$" G\5      Gr%G\&" G\5      Gr'G\(" G\5      Gr)G\*" G\5      Gr+G\," G\5      Gr-G\," G\5      Gr.G\/" G\5      Gr0G\1" G\5      Gr2GSD Gr3 " GSE GSF5      Gr4g(Q  a3  Z3 is a high performance theorem prover developed at Microsoft Research.

Z3 is used in many applications such as: software/hardware verification and testing,
constraint solving, analysis of hybrid systems, security, biology (in silico analysis),
and geometrical problems.


Please send feedback, comments and/or corrections on the Issue tracker for
https://github.com/Z3prover/z3.git. Your comments are very valuable.

Small example:

>>> x = Int('x')
>>> y = Int('y')
>>> s = Solver()
>>> s.add(x > 0)
>>> s.add(x < 2)
>>> s.add(y == x + 1)
>>> s.check()
sat
>>> m = s.model()
>>> m[x]
1
>>> m[y]
2

Z3 exceptions:

>>> try:
...   x = BitVec('x', 32)
...   y = Bool('y')
...   # the expression x + y is type incorrect
...   n = x + y
... except Z3Exception as ex:
...   print("failed: %s" % ex)
failed: sort mismatch
   )z3core)*    )FractionN   )IterableIterator)Callable)Anyr   SequenceTc                      [         $ N)Z3_DEBUG     ?/home/james-whalen/.local/lib/python3.13/site-packages/z3/z3.pyz3_debugr   F   s    Or   c                 .    [        U [        [        45      $ r   )
isinstanceintlongvs    r   _is_intr   L   s    !c4[))r   c                 "    [        U [        5      $ r   )r   r   r   s    r   r   r   O   s    !S!!r   c                     [        U 5        g r   )Z3_enable_tracemsgs    r   enable_tracer    S   s
    Cr   c                     [        U 5        g r   )Z3_disable_tracer   s    r   disable_tracer#   W   s
    Sr   c                     [         R                  S5      n [         R                  S5      n[         R                  S5      n[         R                  S5      n[        XX#5        U R                  < SUR                  < SUR                  < 3$ )Nr   .ctypesc_uintZ3_get_versionvaluemajorminorbuildrevs       r   get_version_stringr0   [   s]    MM!EMM!EMM!E
--
C5,ekk5;;??r   c                     [         R                  S5      n [         R                  S5      n[         R                  S5      n[         R                  S5      n[        XX#5        U R                  UR                  UR                  UR                  4$ Nr   r&   r+   s       r   get_versionr3   d   sc    MM!EMM!EMM!E
--
C5,KKekk399==r   c                      [        5       $ r   )Z3_get_full_versionr   r   r   get_full_versionr6   m   s      r   c                 (    U (       d  [        U5      eg r   Z3Exception)condr   s     r   
_z3_assertr;   q   s    # r   c                 b    [        [        R                  U 5      R                  U :H  US-   5        g )Nz is too large)r;   r'   c_intr*   )nnames     r   _z3_check_cint_overflowr@   v   s$    v||A$$)4/+ABr   c                     [        U 5        g)zSLog interaction to a file. This function must be invoked immediately after init(). N)Z3_open_log)fnames    r   open_logrD   z   s
    r   c                     [        U 5        g)z/Append user-defined string to interaction log. N)Z3_append_logss    r   
append_logrI      s
    !r   c                     [        U 5      (       a#  [        [        U5      R                  5       U 5      $ [	        [        U5      R                  5       U 5      $ )z.Convert an integer or string into a Z3 symbol.)r   Z3_mk_int_symbol_get_ctxrefZ3_mk_string_symbolrH   ctxs     r   	to_symbolrQ      s?    qzz 1 1 3Q77"8C=#4#4#6::r   c                     [        U R                  5       U5      [        :X  a  S[        U R                  5       U5      -  $ [	        U R                  5       U5      $ )z/Convert a Z3 symbol back into a Python object. zk!%s)Z3_get_symbol_kindrM   Z3_INT_SYMBOLZ3_get_symbol_intZ3_get_symbol_stringrP   rH   s     r   
_symbol2pyrX      sC    #'')Q'=8)#'')Q777#CGGIq11r   c                     [        U 5      S:X  a5  [        U S   [        5      (       d  [        U S   [        5      (       a  U S   $ [        U 5      S:X  aE  [        U S   [        5      (       d  [        U S   [
        5      (       a  U S    Vs/ s H  oPM     sn$ [        U 5      S:X  a&  [        U S   [        5      (       a  [        U S   5      $ U $ s  snf ! [         a    U s $ f = fNr   r   )lenr   tuplelistset	AstVectorr	   	TypeErrorargsargs     r   	_get_argsrd      s    
t9>z$q'599ZQQU=V=V7NY!^DGS!9!9ZQQZ=[=[#'7+7CC7++Y!^
47H = =Q= K	 ,
  s7   AC AC CC 4C C C C%$C%c                      [        U [        [        [        45      (       a  U  Vs/ s H  oPM     sn$ U $ s  snf ! [         a    U s $ f = fr   )r   r^   r_   r\   	Exceptionra   s     r   _get_args_ast_listrg      sP    dS)U344#'(4CC4((K )  s   $; 6; ; ; A
	A
c                 X    [        U [        5      (       a  U (       a  S$ S$ [        U 5      $ )Ntruefalse)r   boolstrvals    r   _to_param_valuero      s%    #tv)')s8Or   c                     g r   r   )ces     r   z3_error_handlerrs      s     r   c                   6    \ rS rSrSrS rS rS rS rS r	Sr
g	)
Context   aB  A Context manages all other Z3 objects, global configuration options, etc.

Z3Py uses a default global context. For most applications this is sufficient.
An application may use multiple Z3 contexts. Objects created in one context
cannot be used in another one. However, several objects may be "translated" from
one context to another. It is not safe to access Z3 objects from multiple threads.
The only exception is the method `interrupt()` that can be used to interrupt() a long
computation.
The initialization method receives global configuration options for the new context.
c                    [        5       (       a  [        [        U5      S-  S:H  S5        [        5       nU H4  nX$   n[	        U[        U5      R                  5       [        U5      5        M6     S nU H+  nUc  UnM
  [	        U[        U5      [        U5      5        S nM-     [        U5      U l	        SU l
        [        U R                  [        5      U l        [        U R                  [        5        [!        U5        g )N   r   3Argument list must have an even number of elements.T)r   r;   r[   Z3_mk_configZ3_set_param_valuerl   upperro   Z3_mk_context_rcrP   ownerZ3_set_error_handlerrs   ehZ3_set_ast_print_modeZ3_PRINT_SMTLIB2_COMPLIANTZ3_del_config)selfrb   kwsconfkeyr*   prevas           r   __init__Context.__init__   s    ::s4y1})+`a~CHEtSX^^%5u7MN  A|"4TOA4FG  $D)
&txx1ABdhh(BCdr   c                 z    [         b&  U R                  (       a  [        U R                  5        S U l        S U l        g r   )Z3_del_contextr~   rP   r   r   s    r   __del__Context.__del__   s(    %$**488$r   c                     U R                   $ )z=Return a reference to the actual C pointer to the Z3 context.rP   r   s    r   rM   Context.ref       xxr   c                 6    [        U R                  5       5        g)zInterrupt a solver performing a satisfiability test, a tactic processing a goal, or simplify functions.

This method can be invoked from a thread different from the one executing the
interruptible procedure.
N)Z3_interruptrM   r   s    r   	interruptContext.interrupt   s     	TXXZ r   c                 H    [        [        U R                  5       5      U 5      $ )z,Return the global parameter description set.)ParamDescrsRefZ3_get_global_param_descrsrM   r   s    r   param_descrsContext.param_descrs   s    8DdKKr   )rP   r   r~   N)__name__
__module____qualname____firstlineno____doc__r   r   rM   r   r   __static_attributes__r   r   r   ru   ru      s!    	(!Lr   ru   returnc                  0    [         c
  [        5       q [         $ )zReturn a reference to the global Z3 context.

>>> x = Real('x')
>>> x.ctx == main_ctx()
True
>>> c = Context()
>>> c == main_ctx()
False
>>> x2 = Real('x', c)
>>> x2.ctx == c
True
>>> eq(x, x2)
False
)	_main_ctxru   r   r   r   main_ctxr      s      I	r   c                      U c
  [        5       $ U $ r   )r   r   s    r   rL   rL     s    
{z
r   c                     [        U 5      $ r   )rL   r   s    r   get_ctxr     s    C=r   c                  x   [        5       (       a  [        [        U 5      S-  S:H  S5        0 nU H  nX   n[        X45      (       a  M  XBU'   M     U H3  nX%   n[	        [        U5      R                  5       [        U5      5        M5     SnU  H*  nUc  UnM
  [	        [        U5      [        U5      5        SnM,     g)zCSet Z3 global (or module) parameters.

>>> set_param(precision=10)
rx   r   ry   N)r   r;   r[   set_pp_optionZ3_global_param_setrl   r|   ro   )	rb   r   new_kwskr   r   r*   r   r   s	            r   	set_paramr     s    
 zz3t9q=A%'\]GFQ""AJ  CHNN,oe.DE  D<DD	?1+=>D r   c                      [        5         g)z-Reset all global (or module) parameters.
    N)Z3_global_param_reset_allr   r   r   reset_paramsr   1  s
     r   c                      [        U 0 UD6$ )z6Alias for 'set_param' for backward compatibility.
    )r   )rb   r   s     r   
set_optionr   7  s     d"c""r   c                     [         R                  S-  " 5       n[        [        U 5      U5      (       a  [        R
                  " US   5      nU$ [        SU -  5      e)z]Return the value of a Z3 global (or module) parameter

>>> get_param('nlsat.reorder')
'true'
r   r   z!failed to retrieve value for '%s')r'   c_char_pZ3_global_param_getrl   r   	_to_pystrr9   )r?   ptrrs      r   	get_paramr   =  sP     ??Q
!C3t9c**SV$
9D@
AAr   c                   $    \ rS rSrSrS rS rSrg)
Z3PPObjectiR  zDSuperclass for all Z3 objects that have support for pretty printing.c                     gNTr   r   s    r   use_ppZ3PPObject.use_ppU      r   c                 \    [        5       n[        S5        [        U 5      n[        U5        U$ r   in_html_modeset_html_modereprr   in_htmlress      r   _repr_html_Z3PPObject._repr_html_X  '    .d4jg
r   r   N)r   r   r   r   r   r   r   r   r   r   r   r   r   R  s    Nr   r   c                       \ rS rSrSrSS jrS r0 4S jrS rS r	S	 r
S
 rS rS rS rS rS rS rS rS rS rS rS rSrg)AstRefi`  z[AST are Direct Acyclic Graphs (DAGs) used to represent sorts, declarations and expressions.Nc                     Xl         [        U5      U l        [        U R                  R	                  5       U R                  5       5        g r   )astrL   rP   
Z3_inc_refrM   as_ast)r   r   rP   s      r   r   AstRef.__init__c  s,    C=488<<>4;;=1r   c                     U R                   R                  5       bP  U R                  bB  [        b:  [        U R                   R                  5       U R	                  5       5        S U l        g g g g r   )rP   rM   r   
Z3_dec_refr   r   s    r   r   AstRef.__del__h  sN    88<<>%$((*>:CYtxx||~t{{}5DH DZ*>%r   c                 B    [        U R                  U R                  5      $ r   )_to_ast_refr   rP   r   memos     r   __deepcopy__AstRef.__deepcopy__m  s    488TXX..r   c                     [        U 5      $ r   obj_to_stringr   s    r   __str__AstRef.__str__p      T""r   c                     [        U 5      $ r   r   r   s    r   __repr__AstRef.__repr__s  r   r   c                 $    U R                  U5      $ r   eqr   others     r   __eq__AstRef.__eq__v  s    wwu~r   c                 "    U R                  5       $ r   )hashr   s    r   __hash__AstRef.__hash__y  s    yy{r   c                 "    U R                  5       $ r   )__bool__r   s    r   __nonzero__AstRef.__nonzero__|  s    }}r   c                    [        U 5      (       a  g[        U 5      (       a  g[        U 5      (       aC  U R                  5       S:X  a/  U R	                  S5      R                  U R	                  S5      5      $ [        S5      e)NTFrx   r   r   z?Symbolic expressions cannot be cast to concrete Boolean values.)is_trueis_falseis_eqnum_argsrc   r   r9   r   s    r   r   AstRef.__bool__  s[    4==d^^4[[T]]_188A;>>$((1+.._``r   c                 R    [        U R                  5       U R                  5       5      $ )z~Return a string representing the AST node in s-expression notation.

>>> x = Int('x')
>>> ((x + 1)*x).sexpr()
'(* (+ x 1) x)'
Z3_ast_to_stringctx_refr   r   s    r   sexprAstRef.sexpr  s      >>r   c                     U R                   $ )z6Return a pointer to the corresponding C Z3_ast object.r   r   s    r   r   AstRef.as_ast  r   r   c                 R    [        U R                  5       U R                  5       5      $ )zMReturn unique identifier for object. It can be used for hash-tables and maps.Z3_get_ast_idr   r   r   s    r   get_idAstRef.get_id  s    T\\^T[[];;r   c                 6    U R                   R                  5       $ )zBReturn a reference to the C context where this AST node is stored.rP   rM   r   s    r   r   AstRef.ctx_ref  s    xx||~r   c                     [        5       (       a  [        [        U5      S5        [        U R	                  5       U R                  5       UR                  5       5      $ )zReturn `True` if `self` and `other` are structurally identical.

>>> x = Int('x')
>>> n1 = x + 1
>>> n2 = 1 + x
>>> n1.eq(n2)
False
>>> n1 = simplify(n1)
>>> n2 = simplify(n2)
>>> n1.eq(n2)
True
zZ3 AST expected)r   r;   is_astZ3_is_eq_astr   r   r   s     r   r   	AstRef.eq  s;     ::ve}&78DLLNDKKM5<<>JJr   c                     [        5       (       a  [        [        U[        5      S5        [	        [        U R                  R                  5       U R                  5       UR                  5       5      U5      $ )aJ  Translate `self` to the context `target`. That is, return a copy of `self` in the context `target`.

>>> c1 = Context()
>>> c2 = Context()
>>> x  = Int('x', c1)
>>> y  = Int('y', c2)
>>> # Nodes in different contexts can't be mixed.
>>> # However, we can translate nodes from one context to another.
>>> x.translate(c2) + y
x + y
argument must be a Z3 context)	r   r;   r   ru   r   Z3_translaterP   rM   r   r   targets     r   	translateAstRef.translate  sJ     ::z&'24ST<vzz|TV\]]r   c                 8    U R                  U R                  5      $ r   r  rP   r   s    r   __copy__AstRef.__copy__      ~~dhh''r   c                 R    [        U R                  5       U R                  5       5      $ )zReturn a hashcode for the `self`.

>>> n1 = simplify(Int('x') + 1)
>>> n2 = simplify(2 + Int('x') - 1)
>>> n1.hash() == n2.hash()
True
)Z3_get_ast_hashr   r   r   s    r   r   AstRef.hash  s     t||~t{{}==r   c                     g)z3Return a Python value that is equivalent to `self`.Nr   r   s    r   py_valueAstRef.py_value  s    r   )r   rP   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r	  r   r   r  r  r   r"  r   r   r   r   r   r   `  sg    e2

 !# /##a?<K"^ (>r   r   r   c                 "    [        U [        5      $ )zReturn `True` if `a` is an AST node.

>>> is_ast(10)
False
>>> is_ast(IntVal(10))
True
>>> is_ast(Int('x'))
True
>>> is_ast(BoolSort())
True
>>> is_ast(Function('f', IntSort(), IntSort()))
True
>>> is_ast("x")
False
>>> is_ast(Solver())
False
)r   r   r   s    r   r  r    s    $ a  r   bc                     [        5       (       a'  [        [        U 5      =(       a    [        U5      S5        U R                  U5      $ )zReturn `True` if `a` and `b` are structurally identical AST nodes.

>>> x = Int('x')
>>> y = Int('y')
>>> eq(x, y)
False
>>> eq(x + 1, x + 1)
True
>>> eq(x + 1, 1 + x)
False
>>> eq(simplify(x + 1), simplify(1 + x))
True
zZ3 ASTs expected)r   r;   r  r   r   r&  s     r   r   r     s0     zz6!9*,>?447Nr   rP   c                 v    [        U5      (       a  UR                  5       n[        U R                  5       U5      $ r   )r  r   Z3_get_ast_kindrM   rP   r   s     r   	_ast_kindr,    s)    ayyHHJ3779a((r   c                     S nU  H_  n[        U5      (       d  [        U5      (       d  M%  Uc  UR                  nM6  [        5       (       d  MG  [	        X#R                  :H  S5        Ma     Uc  UnU$ NContext mismatch)r  is_proberP   r   r;   )rb   default_ctxrP   r   s       r   _ctx_from_ast_arg_listr2    sY    
C!99{ee::see|-?@  {Jr   c                      [        U 5      $ r   )r2  )rb   s    r   _ctx_from_ast_argsr4    s    !$''r   c                     [        U 5      n[        U-  " 5       n[        U5       H  nX   R                  5       X#'   M     X!4$ r   )r[   FuncDeclrangeas_func_declrb   sz_argsis       r   _to_func_decl_arrayr=    s?    	TB]E2Y7'') 9r   c                     [        U 5      n[        U-  " 5       n[        U5       H  nX   R                  5       X#'   M     X!4$ r   )r[   Astr7  r   r9  s       r   _to_ast_arrayr@    s<    	TB2XLE2Y7>># 9r   c                 |    [        U5      nX-  " 5       n[        U5       H  nX   R                  5       X4'   M     X24$ r   )r[   r7  r   )rM   rb   r:  r;  r<  s        r   _to_ref_arrayrB  !  s:    	TBXLE2Y7>># 9r   c                     [        X5      nU[        :X  a  [        X5      $ U[        :X  a  [	        X5      $ [        X5      $ r   )r,  Z3_SORT_AST_to_sort_refZ3_FUNC_DECL_AST_to_func_decl_ref_to_expr_ref)r   rP   r   s      r   r   r   )  s>    #AKA##	
	 ((A##r   c                 6    [        U R                  5       U5      $ r   )Z3_get_sort_kindrM   rW   s     r   
_sort_kindrK  9  s    CGGIq))r   c                   T    \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rSrg)SortRefi=  zTA Sort is essentially a type. Every Z3 expression has a sort. A sort is an AST node.c                 J    [        U R                  5       U R                  5      $ r   )Z3_sort_to_astr   r   r   s    r   r   SortRef.as_ast@  s    dllndhh77r   c                 R    [        U R                  5       U R                  5       5      $ r   r  r   s    r   r	  SortRef.get_idC      T\\^T[[];;r   c                 B    [        U R                  U R                  5      $ )a6  Return the Z3 internal kind of a sort.
This method can be used to test if `self` is one of the Z3 builtin sorts.

>>> b = BoolSort()
>>> b.kind() == Z3_BOOL_SORT
True
>>> b.kind() == Z3_INT_SORT
False
>>> A = ArraySort(IntSort(), IntSort())
>>> A.kind() == Z3_ARRAY_SORT
True
>>> A.kind() == Z3_INT_SORT
False
)rK  rP   r   r   s    r   kindSortRef.kindF  s     $((DHH--r   c                     g)zYReturn `True` if `self` is a subsort of `other`.

>>> IntSort().subsort(RealSort())
True
Fr   r   s     r   subsortSortRef.subsortW  s     r   c                     [        5       (       a>  [        [        U5      S5        [        U R                  UR	                  5       5      S5        U$ )zTry to cast `val` as an element of sort `self`.

This method is used in Z3Py to convert Python objects such as integers,
floats, longs and strings into Z3 expressions.

>>> x = Int('x')
>>> RealSort().cast(x)
ToReal(x)
Z3 expression expectedzSort mismatch)r   r;   is_exprr   sortr   rn   s     r   castSortRef.cast_  s8     ::ws|%=>twwsxxz*O<
r   c                 r    [        U R                  [        U R                  5       U R                  5      5      $ )zzReturn the name (string) of sort `self`.

>>> BoolSort().name()
'Bool'
>>> ArraySort(IntSort(), IntSort()).name()
'Array'
)rX   rP   Z3_get_sort_namer   r   r   s    r   r?   SortRef.namen  s'     $(($4T\\^TXX$NOOr   c                 h    Uc  g[        U R                  5       U R                  UR                  5      $ )zReturn `True` if `self` and `other` are the same Z3 sort.

>>> p = Bool('p')
>>> p.sort() == BoolSort()
True
>>> p.sort() == IntSort()
False
FZ3_is_eq_sortr   r   r   s     r   r   SortRef.__eq__x  s)     =T\\^TXXuyyAAr   c                 j    [        U R                  5       U R                  UR                  5      (       + $ )zReturn `True` if `self` and `other` are not the same Z3 sort.

>>> p = Bool('p')
>>> p.sort() != BoolSort()
False
>>> p.sort() != IntSort()
True
re  r   s     r   __ne__SortRef.__ne__  s$     !599EEEr   c                     [        X5      $ )z,Create the function space Array(self, other))	ArraySortr   s     r   __gt__SortRef.__gt__  s    %%r   c                 ,    [         R                  U 5      $ zHash code. r   r   r   s    r   r   SortRef.__hash__      t$$r   r   N)r   r   r   r   r   r   r	  rU  rX  r_  r?   r   ri  rm  r   r   r   r   r   rM  rM  =  s:    ^8<."PB	F&%r   rM  rH   c                 "    [        U [        5      $ )zwReturn `True` if `s` is a Z3 sort.

>>> is_sort(IntSort())
True
>>> is_sort(Int('x'))
False
>>> is_expr(Int('x'))
True
)r   rM  rG   s    r   is_sortru         a!!r   c                    [        5       (       a  [        [        U [        5      S5        [	        X5      nU[
        :X  a  [        X5      $ U[        :X  d
  U[        :X  a  [        X5      $ U[        :X  a  [        X5      $ U[        :X  a  [        X5      $ U[        :X  a  [        X5      $ U[         :X  a  [#        X5      $ U[$        :X  a  ['        X5      $ U[(        :X  a  [+        X5      $ U[,        :X  a  [/        X5      $ U[0        :X  a  [3        X5      $ U[4        :X  a  [7        X5      $ U[8        :X  a  [;        X5      $ [=        X5      $ )NzZ3 Sort expected)r   r;   r   SortrK  Z3_BOOL_SORTBoolSortRefZ3_INT_SORTZ3_REAL_SORTArithSortRef
Z3_BV_SORTBitVecSortRefZ3_ARRAY_SORTArraySortRefZ3_DATATYPE_SORTDatatypeSortRefZ3_FINITE_DOMAIN_SORTFiniteDomainSortRefZ3_FLOATING_POINT_SORT	FPSortRefZ3_ROUNDING_MODE_SORTFPRMSortRef
Z3_RE_SORT	ReSortRefZ3_SEQ_SORT
SeqSortRefZ3_CHAR_SORTCharSortRefZ3_TYPE_VAR
TypeVarRefrM  )rH   rP   r   s      r   rE  rE    s   zz:a&(:;3AL1""	
k	Q,.A##	
jQ$$	
m	A##	
	q&&	
#	#"1**	
$	$  	
#	#1""	
j  	
k	!!!	
l	1""	
k	!!!1?r   c                 J    [        [        U R                  5       U5      U 5      $ r   )rE  Z3_get_sortrM   r+  s     r   _sortr    s    CGGIq1377r   c           	      r    [        U5      n[        [        UR                  5       [	        X5      5      U5      $ )zCreate a new uninterpreted sort named `name`.

If `ctx=None`, then the new sort is declared in the global Z3Py context.

>>> A = DeclareSort('A')
>>> a = Const('a', A)
>>> b = Const('b', A)
>>> a.sort() == A
True
>>> b.sort() == A
True
>>> a == b
a == b
)rL   rM  Z3_mk_uninterpreted_sortrM   rQ   r?   rP   s     r   DeclareSortr    s-     3-C+CGGIy7KLcRRr   c                   $    \ rS rSrSrS rS rSrg)r  i  zType variable referencec                     gr   r   r   s     r   rX  TypeVarRef.subsort  r   r   c                     U$ r   r   r^  s     r   r_  TypeVarRef.cast  s    
r   r   N)r   r   r   r   r   rX  r_  r   r   r   r   r  r    s    !r   r  c           	      r    [        U5      n[        [        UR                  5       [	        X5      5      U5      $ )ztCreate a new type variable named `name`.

If `ctx=None`, then the new sort is declared in the global Z3Py context.

)rL   r  Z3_mk_type_variablerM   rQ   r  s     r   DeclareTypeVarr    s-     3-C)#'')Yt5IJCPPr   c                   T    \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rSrg)FuncDeclRefi  a  Function declaration. Every constant and function have an associated declaration.

The declaration assigns a name, a sort (i.e., type), and for function
the sort (i.e., type) of each of its arguments. Note that, in Z3,
a constant is a function with 0 arguments.
c                 J    [        U R                  5       U R                  5      $ r   )Z3_func_decl_to_astr   r   r   s    r   r   FuncDeclRef.as_ast  s    "4<<>488<<r   c                 R    [        U R                  5       U R                  5       5      $ r   r  r   s    r   r	  FuncDeclRef.get_id  rS  r   c                     U R                   $ r   r  r   s    r   r8  FuncDeclRef.as_func_decl      xxr   c                 r    [        U R                  [        U R                  5       U R                  5      5      $ )zReturn the name of the function declaration `self`.

>>> f = Function('f', IntSort(), IntSort())
>>> f.name()
'f'
>>> isinstance(f.name(), str)
True
)rX   rP   Z3_get_decl_namer   r   r   s    r   r?   FuncDeclRef.name  s'     $(($4T\\^TXX$NOOr   c                 \    [        [        U R                  5       U R                  5      5      $ )zReturn the number of arguments of a function declaration.
If `self` is a constant, then `self.arity()` is 0.

>>> f = Function('f', IntSort(), RealSort(), BoolSort())
>>> f.arity()
2
)r   Z3_get_arityr   r   r   s    r   arityFuncDeclRef.arity  s      <9::r   c                 t    [        [        U R                  5       U R                  U5      U R                  5      $ )zReturn the sort of the argument `i` of a function declaration.
This method assumes that `0 <= i < self.arity()`.

>>> f = Function('f', IntSort(), RealSort(), BoolSort())
>>> f.domain(0)
Int
>>> f.domain(1)
Real
)rE  Z3_get_domainr   r   rP   r   r<  s     r   domainFuncDeclRef.domain  s(     M$,,.$((AFQQr   c                 r    [        [        U R                  5       U R                  5      U R                  5      $ )zReturn the sort of the range of a function declaration.
For constants, this is the sort of the constant.

>>> f = Function('f', IntSort(), RealSort(), BoolSort())
>>> f.range()
Bool
)rE  Z3_get_ranger   r   rP   r   s    r   r7  FuncDeclRef.range(  s&     LBDHHMMr   c                 J    [        U R                  5       U R                  5      $ )zReturn the internal kind of a function declaration.
It can be used to identify Z3 built-in functions such as addition, multiplication, etc.

>>> x = Int('x')
>>> d = (x + 1).decl()
>>> d.kind() == Z3_OP_ADD
True
>>> d.kind() == Z3_OP_MUL
False
)Z3_get_decl_kindr   r   r   s    r   rU  FuncDeclRef.kind2  s      99r   c                 f   U R                   n[        U R                  5       U R                  5      n[	        U5       Vs/ s H  nS PM     nn[	        U5       GH  n[        U R                  5       U R                  U5      nU[        :X  a)  [        U R                  5       U R                  U5      XC'   M\  U[        :X  a)  [        U R                  5       U R                  U5      XC'   M  U[        :X  a)  [        U R                  5       U R                  U5      XC'   M  U[        :X  a)  [        U R                  5       U R                  U5      XC'   M  U[        :X  a4  [        [!        U R                  5       U R                  U5      U5      XC'   GM3  U["        :X  a4  [%        ['        U R                  5       U R                  U5      U5      XC'   GMq  U[(        :X  a4  [+        [-        U R                  5       U R                  U5      U5      XC'   GM  U[.        :X  a  SXC'   GM  U[0        :X  a  SXC'   GM   e   U$ s  snf )Nzinternal parameterzinternal string)rP   Z3_get_decl_num_parametersr   r   r7  Z3_get_decl_parameter_kindZ3_PARAMETER_INTZ3_get_decl_int_parameterZ3_PARAMETER_DOUBLEZ3_get_decl_double_parameterZ3_PARAMETER_RATIONALZ3_get_decl_rational_parameterZ3_PARAMETER_SYMBOLZ3_get_decl_symbol_parameterZ3_PARAMETER_SORTrM  Z3_get_decl_sort_parameterZ3_PARAMETER_ASTExprRefZ3_get_decl_ast_parameterZ3_PARAMETER_FUNC_DECLr  Z3_get_decl_func_decl_parameterZ3_PARAMETER_INTERNALZ3_PARAMETER_ZSTRING)r   rP   r>   r<  resultr   s         r   paramsFuncDeclRef.params?  s   hh&t||~txx@ %a)1$)qA*4<<>488QGA$$5dllndhhPQR	))8STU	++:4<<>488UVW	))8STU	''#$>t||~txxYZ$[]`a	&&#$=dllndhhXY$Z\_`	,,'(GX\X`X`bc(dfij	++0	**-	u+ , / *s   H.c           	         [        U5      n[        U5      n[        U-  " 5       n/ n[        U5       HH  nU R	                  U5      R                  X   5      nUR                  U5        UR                  5       X5'   MJ     [        [        U R                  5       U R                  [        U5      U5      U R                  5      $ )a  Create a Z3 application expression using the function `self`, and the given arguments.

The arguments must be Z3 expressions. This method assumes that
the sorts of the elements in `args` match the sorts of the
domain. Limited coercion is supported.  For example, if
args[0] is a Python integer, and the function expects a Z3
integer, then the argument is automatically converted into a
Z3 integer.

>>> f = Function('f', IntSort(), RealSort(), BoolSort())
>>> x = Int('x')
>>> y = Real('y')
>>> f(x, y)
f(x, y)
>>> f(x, x)
f(x, ToReal(x))
)rd   r[   r?  r7  r  r_  appendr   rH  	Z3_mk_appr   r   rP   )r   rb   numr;  savedr<  tmps          r   __call__FuncDeclRef.__call__[  s    $ $issA ++a.%%dg.CLLzz|EH  IdllndhhD	5QSWS[S[\\r   r   N)r   r   r   r   r   r   r	  r8  r?   r  r  r7  rU  r  r  r   r   r   r   r  r    s=    =<	P;
RN:8]r   r  c                 "    [        U [        5      $ )zReturn `True` if `a` is a Z3 function declaration.

>>> f = Function('f', IntSort(), IntSort())
>>> is_func_decl(f)
True
>>> x = Real('x')
>>> is_func_decl(x)
False
)r   r  r%  s    r   is_func_declr  z  s     a%%r   c           	         [        U5      n[        5       (       a  [        [        U5      S:  S5        [        U5      S-
  nX   n[        5       (       a  [        [	        U5      S5        [
        U-  " 5       n[        U5       H9  n[        5       (       a  [        [	        X   5      S5        X   R                  XE'   M;     UR                  n[        [        UR                  5       [        X5      X$UR                  5      U5      $ )z~Create a new Z3 uninterpreted function with the given sorts.

>>> f = Function('f', IntSort(), IntSort())
>>> f(f(0))
f(f(0))
r   At least two arguments expectedr   Z3 sort expected)rd   r   r;   r[   ru  rx  r7  r   rP   r  Z3_mk_func_declrM   rQ   r?   sigr  rngdomr<  rP   s          r   Functionr    s     C.Czz3s8a<!BCHqLE
*Czz73<!34%<
C5\::wsv(:;  ''Cswwy)D2FTWT[T[\^abbr   c            	      
   [        U 5      n [        5       (       a  [        [        U 5      S:  S5        [        U 5      S-
  nX   n[        5       (       a  [        [	        U5      S5        [
        R                  U-  " 5       n[        U5       H9  n[        5       (       a  [        [	        X   5      S5        X   R                  X4'   M;     UR                  n[        [        UR                  5       SXUR                  5      U5      $ )zGCreate a new fresh Z3 uninterpreted function with the given sorts.
    r   r  r   r  f)rd   r   r;   r[   ru  z3rx  r7  r   rP   r  Z3_mk_fresh_func_declrM   )r  r  r  r  r<  rP   s         r   FreshFunctionr    s     C.Czz3s8a<!BCHqLE
*Czz73<!3477U?
C5\::wsv(:;  ''C,SWWYUQSVWWr   c                     [        X5      $ r   )r  r   rP   s     r   rG  rG    s    qr   c           	         [        U5      n[        5       (       a  [        [        U5      S:  S5        [        U5      S-
  nX   n[        5       (       a  [        [	        U5      S5        [
        U-  " 5       n[        U5       H9  n[        5       (       a  [        [	        X   5      S5        X   R                  XE'   M;     UR                  n[        [        UR                  5       [        X5      X$UR                  5      U5      $ )z/Create a new Z3 recursive with the given sorts.r   r  r   r  )rd   r   r;   r[   ru  rx  r7  r   rP   r  Z3_mk_rec_func_declrM   rQ   r  s          r   RecFunctionr    s    
C.Czz3s8a<!BCHqLE
*Czz73<!34%<
C5\::wsv(:;  ''C*3779i6JEX[X_X_`beffr   c                 .   [        U5      (       a  U/nUR                  n[        U5      n[        U5      n[        U-  " 5       n[        U5       H  nX   R                  XV'   M     [        UR                  5       U R                  XEUR                  5        g)a  Set the body of a recursive function.
   Recursive definitions can be simplified if they are applied to ground
   arguments.
>>> ctx = Context()
>>> fac = RecFunction('fac', IntSort(ctx), IntSort(ctx))
>>> n = Int('n', ctx)
>>> RecAddDefinition(fac, n, If(n == 0, 1, n*fac(n-1)))
>>> simplify(fac(5))
120
>>> s = Solver(ctx=ctx)
>>> s.add(fac(n) < 3)
>>> s.check()
sat
>>> s.model().eval(fac(5))
120
N)	is_apprP   rd   r[   r?  r7  r   Z3_add_rec_defrM   )r  rb   bodyrP   r>   r;  r<  s          r   RecAddDefinitionr    sq    " d||v
((CT?DD	A1WKE1X7;; 3779aeeQtxx8r   c                   r    \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rS rS rS rS rS rSrg)r  i  aP  Constraints, formulas and terms are expressions in Z3.

Expressions are ASTs. Every expression has a sort.
There are three main kinds of expressions:
function applications, quantifiers and bounded variables.
A constant is a function application with 0 arguments.
For quantifier free problems, all expressions are
function applications.
c                     U R                   $ r   r  r   s    r   r   ExprRef.as_ast  r  r   c                 R    [        U R                  5       U R                  5       5      $ r   r  r   s    r   r	  ExprRef.get_id  rS  r   c                 J    [        U R                  U R                  5       5      $ )zyReturn the sort of expression `self`.

>>> x = Int('x')
>>> (x + 1).sort()
Int
>>> y = Real('y')
>>> (x + y).sort()
Real
)r  rP   r   r   s    r   r]  ExprRef.sort  s     TXXt{{}--r   c                 >    U R                  5       R                  5       $ )zShorthand for `self.sort().kind()`.

>>> a = Array('a', IntSort(), IntSort())
>>> a.sort_kind() == Z3_ARRAY_SORT
True
>>> a.sort_kind() == Z3_INT_SORT
False
)r]  rU  r   s    r   	sort_kindExprRef.sort_kind       yy{!!r   c                     Uc  g[        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zReturn a Z3 expression that represents the constraint `self == other`.

If `other` is `None`, then this method simply returns `False`.

>>> a = Int('a')
>>> b = Int('b')
>>> a == b
a == b
>>> a is None
False
F)_coerce_exprsBoolRefZ3_mk_eqr   r   rP   r   r   r   r&  s       r   r   ExprRef.__eq__  sD     =T)x
AHHJGRRr   c                 ,    [         R                  U 5      $ rp  rq  r   s    r   r   ExprRef.__hash__"  rs  r   c                     Uc  g[        X5      u  p#[        X#45      u  pE[        [        U R	                  5       SU5      U R
                  5      $ )zReturn a Z3 expression that represents the constraint `self != other`.

If `other` is `None`, then this method simply returns `True`.

>>> a = Int('a')
>>> b = Int('b')
>>> a != b
a != b
>>> a is not None
True
Trx   )r  r@  r  Z3_mk_distinctr   rP   )r   r   r   r&  r;  r:  s         r   ri  ExprRef.__ne__&  sF     =T)!1&)	~dllna?JJr   c                 >    U R                  5       R                  5       $ r   )declr  r   s    r   r  ExprRef.params8  s    yy{!!##r   c                     [        5       (       a  [        [        U 5      S5        [        [	        U R                  5       U R                  5       5      U R                  5      $ )zReturn the Z3 function declaration associated with a Z3 application.

>>> f = Function('f', IntSort(), IntSort())
>>> a = Int('a')
>>> t = f(a)
>>> eq(t.decl(), f)
True
>>> (a + 1).decl()
+
Z3 application expected)r   r;   r  r  Z3_get_app_declr   r   rP   r   s    r   r  ExprRef.decl;  s>     ::vd|%>??4<<>4;;=I488TTr   c                     [        5       (       a  [        [        U 5      S5        [        U R	                  5       [        U R	                  5       U R                  5      5      $ )z6Return the Z3 internal kind of a function application.r  )r   r;   r  r  r   r  r   r   s    r   rU  ExprRef.kindJ  s?    ::vd|%>?PTPXPX0YZZr   c                     [        5       (       a  [        [        U 5      S5        [        [	        U R                  5       U R                  5       5      5      $ )zReturn the number of arguments of a Z3 application.

>>> a = Int('a')
>>> b = Int('b')
>>> (a + b).num_args()
2
>>> f = Function('f', IntSort(), IntSort(), IntSort(), IntSort())
>>> t = f(a, b, 0)
>>> t.num_args()
3
r  )r   r;   r  r   Z3_get_app_num_argsr   r   r   s    r   r   ExprRef.num_argsQ  s9     ::vd|%>?&t||~t{{}EFFr   c                     [        5       (       a1  [        [        U 5      S5        [        XR                  5       :  S5        [	        [        U R                  5       U R                  5       U5      U R                  5      $ )a2  Return argument `idx` of the application `self`.

This method assumes that `self` is a function application with at least `idx+1` arguments.

>>> a = Int('a')
>>> b = Int('b')
>>> f = Function('f', IntSort(), IntSort(), IntSort(), IntSort())
>>> t = f(a, b, 0)
>>> t.arg(0)
a
>>> t.arg(1)
b
>>> t.arg(2)
0
r  zInvalid argument index)	r   r;   r  r   rH  Z3_get_app_argr   r   rP   r   idxs     r   rc   ExprRef.arga  sW      ::vd|%>?s]]_,.FGN4<<>4;;=#NPTPXPXYYr   c                     [        U 5      (       a8  [        U R                  5       5       Vs/ s H  oR                  U5      PM     sn$ / $ s  snf )zReturn a list containing the children of the given expression

>>> a = Int('a')
>>> b = Int('b')
>>> f = Function('f', IntSort(), IntSort(), IntSort(), IntSort())
>>> t = f(a, b, 0)
>>> t.children()
[a, b, 0]
)r  r7  r   rc   r  s     r   childrenExprRef.childrenv  s@     $<<).t}})?@)?AHHQK)?@@I As   Ac                     g r   r   r   rH   s     r   from_stringExprRef.from_string  s    r   c                     [        5       n[        SU R                  5       [        U R                  5      5      nUR                  U" U 5      5        UR                  5       $ )NF)Solverr  r]  BoolSortrP   addr  )r   rH   r  s      r   	serializeExprRef.serialize  sA    HS$))+x'9:	agwwyr   r   N)r   r   r   r   r   r   r	  r]  r  r   r   ri  r  r  rU  r   rc   r  r"  r)  r   r   r   r   r  r    sX    <
.	"S"%K$$U[G Z*r   r  c                    [        5       nUR                  U 5        [        UR                  5       5      S:w  a  [	        S5      eUR                  5       S   nUR                  5       S:w  a  [	        S5      eUR                  S5      $ )zinverse function to the serialize method on ExprRef.
It is made available to make it easier for users to serialize expressions back and forth between
strings. Solvers can be serialized using the 'sexpr()' method.
r   zsingle assertion expectedr   zdummy function 'F' expected)r&  r"  r[   
assertionsr9   r   rc   )strH   fmls      r   deserializer/    sn    
 	AMM"
1<<>a566
,,.
C
||~788771:r   c                    [        U [        5      (       a  [        X5      $ UR                  5       n[	        X 5      nU[
        :X  a  [        X5      $ [        U[        X 5      5      nU[        :X  a  [        X5      $ U[        :X  a   U[        :X  a  [        X5      $ [        X5      $ U[        :X  a;  U[        :X  a  [!        X5      $ [#        X5      (       a  [%        X5      $ [        X5      $ U[&        :X  a   U[        :X  a  [)        X5      $ [+        X5      $ U[,        :X  a  [/        X5      $ U[0        :X  a  [3        X5      $ U[4        :X  a0  U[6        :X  a  [9        X5      (       a  [;        X5      $ [=        X5      $ U[>        :X  a   U[        :X  a  [A        X5      $ [C        X5      $ U[D        :X  a  [G        X5      $ U[H        :X  a  [K        X5      $ U[L        :X  a  [O        X5      $ U[P        :X  a  [S        X5      $ [U        X5      $ r   )+r   Pattern
PatternRefrM   r*  Z3_QUANTIFIER_ASTQuantifierRefrJ  r  ry  r  r{  Z3_NUMERAL_AST	IntNumRefArithRefr|  	RatNumRef_is_algebraicAlgebraicNumRefr~  BitVecNumRef	BitVecRefr  ArrayRefr  DatatypeRefr  
Z3_APP_AST_is_numeralFPNumRefFPRefr  FiniteDomainNumRefFiniteDomainRefr  FPRMRefr  SeqRefr  CharRefr  ReRefr  )r   rP   r   r   sks        r   rH  rH    s   !W!!!ggiG#AQ$$	';w#:	;B	\q	[Q$$	\Q$$  "1**	Z''Q$$	]	1""	##
?{322A##= 	""%a--"1**	""q	[a~	\q	ZQ}1?r   c                 `   [        U5      (       a  UR                  5       nU c  U$ UR                  U 5      (       a  U $ U R                  U5      (       a  U$ UR                  U 5      (       a  U $ [	        5       (       a0  [        UR                  U R                  :H  S5        [        SS5        g g U $ )Ncontext mismatchFsort mismatch)r\  r]  r   rX  r   r;   rP   )rH   r   s1s      r   _coerce_expr_mergerN    s    qzzVVX9I5588HYYr]]IZZ]]Hzz266QUU?,>?5/2  r   c                    [        U 5      (       d&  [        U5      (       d  [        X5      n [        X5      n[        U [        5      (       a*  [        U[        5      (       a  [        XR                  5      n [        U[        5      (       a*  [        U [        5      (       a  [        XR                  5      n[        U [        5      (       a*  [        U[        5      (       a  [        XR                  5      n [        U[        5      (       a*  [        U [        5      (       a  [        XR                  5      nS n[        X05      n[        X15      nUR                  U 5      n UR                  U5      nX4$ r   )r\  _py2exprr   rl   rF  	StringValrP   floatr7  RealValrN  r_  r   r&  rP   rH   s       r   r  r    s    1::gajjQQ!SjF33a!SjF33a!U
1h 7 7Auu!U
1h 7 7AuuA1 A1 A	q	A	q	A6Mr   c                 ,    UnU H  nU " X45      nM     U$ r   r   )funcsequenceinitialr  elements        r   _reducerZ    s     Ff& Mr   c                     SnU  H  n[        U5      (       d  M  Sn  O   U(       d  U  Vs/ s H  n[        X15      PM     n n[        [        U S 5      nU  Vs/ s H  o4R	                  U5      PM     sn$ s  snf s  snf )NFT)r\  rP  rZ  rN  r_  )alistrP   has_exprr   rH   s        r   _coerce_expr_listr^    sr    H1::H  +015a!!51"E40A$%u!FF1Iu%% 2%s   A4A9c                 "    [        U [        5      $ )a  Return `True` if `a` is a Z3 expression.

>>> a = Int('a')
>>> is_expr(a)
True
>>> is_expr(a + 1)
True
>>> is_expr(IntSort())
False
>>> is_expr(1)
False
>>> is_expr(IntVal(1))
True
>>> x = Int('x')
>>> is_expr(ForAll(x, x >= 0))
True
>>> is_expr(FPVal(1.0))
True
)r   r  r%  s    r   r\  r\  	  s    ( a!!r   c                     [        U [        5      (       d  g[        U R                  U 5      nU[        :H  =(       d	    U[
        :H  $ )a1  Return `True` if `a` is a Z3 function application.

Note that, constants are function applications with 0 arguments.

>>> a = Int('a')
>>> is_app(a)
True
>>> is_app(a + 1)
True
>>> is_app(IntSort())
False
>>> is_app(1)
False
>>> is_app(IntVal(1))
True
>>> x = Int('x')
>>> is_app(ForAll(x, x >= 0))
False
F)r   r  r,  rP   r5  r?  r   r   s     r   r  r     s8    ( a!!!%%A1!z/1r   c                 L    [        U 5      =(       a    U R                  5       S:H  $ )zReturn `True` if `a` is Z3 constant/variable expression.

>>> a = Int('a')
>>> is_const(a)
True
>>> is_const(a + 1)
False
>>> is_const(1)
False
>>> is_const(IntVal(1))
True
>>> x = Int('x')
>>> is_const(ForAll(x, x >= 0))
False
r   )r  r   r%  s    r   is_constrc  :  s      !9***r   c                 `    [        U 5      =(       a    [        U R                  U 5      [        :H  $ )a  Return `True` if `a` is variable.

Z3 uses de-Bruijn indices for representing bound variables in
quantifiers.

>>> x = Int('x')
>>> is_var(x)
False
>>> is_const(x)
True
>>> f = Function('f', IntSort(), IntSort())
>>> # Z3 replaces x with bound variables when ForAll is executed.
>>> q = ForAll(x, f(x) == x)
>>> b = q.body()
>>> b
f(Var(0)) == Var(0)
>>> b.arg(1)
Var(0)
>>> is_var(b.arg(1))
True
)r\  r,  rP   
Z3_VAR_ASTr%  s    r   is_varrf  M  s#    , 1:;)AEE1-;;r   c                     [        5       (       a  [        [        U 5      S5        [        [	        U R
                  R                  5       U R                  5       5      5      $ )a  Return the de-Bruijn index of the Z3 bounded variable `a`.

>>> x = Int('x')
>>> y = Int('y')
>>> is_var(x)
False
>>> is_const(x)
True
>>> f = Function('f', IntSort(), IntSort(), IntSort())
>>> # Z3 replaces x and y with bound variables when ForAll is executed.
>>> q = ForAll([x, y], f(x, y) == x + y)
>>> q.body()
f(Var(1), Var(0)) == Var(1) + Var(0)
>>> b = q.body()
>>> b.arg(0)
f(Var(1), Var(0))
>>> v1 = b.arg(0).arg(0)
>>> v2 = b.arg(0).arg(1)
>>> v1
Var(1)
>>> v2
Var(0)
>>> get_var_index(v1)
1
>>> get_var_index(v2)
0
zZ3 bound variable expected)r   r;   rf  r   Z3_get_index_valuerP   rM   r   r%  s    r   get_var_indexri  f  s=    8 zz6!9:;!!%%))+qxxz:;;r   c                 L    [        U 5      =(       a    U R                  5       U:H  $ )zReturn `True` if `a` is an application of the given kind `k`.

>>> x = Int('x')
>>> n = x + 1
>>> is_app_of(n, Z3_OP_ADD)
True
>>> is_app_of(n, Z3_OP_MUL)
False
)r  rU  ra  s     r   	is_app_ofrk    s     !9&Q&r   c           	         [        U [        5      (       d*  [        U[        5      (       d  [        U[        5      (       a  [        XX#5      $ [	        [        XU/U5      5      n[        U5      nUR                  U 5      n [        XU5      u  p[        5       (       a#  [        U R                  UR                  :H  S5        [        [        UR                  5       U R                  5       UR                  5       UR                  5       5      U5      $ )zCreate a Z3 if-then-else expression.

>>> x = Int('x')
>>> y = Int('y')
>>> max = If(x > y, x, y)
>>> max
If(x > y, x, y)
>>> simplify(max)
If(x <= y, y, x)
r/  )r   ProbeTacticCondrL   r2  r'  r_  r  r   r;   rP   rH  	Z3_mk_iterM   r   )r   r&  rq   rP   rH   s        r   Ifrq    s     !Uz!V44
1f8M8MA!!!-qQi=>SMFF1IQ3'::quu~'9:IcggiQXXZTVYZZr   c                      [        U 5      n [        U 5      n[        5       (       a  [        USLS5        [	        X5      n [        U 5      u  p#[        [        UR                  5       X25      U5      $ )a)  Create a Z3 distinct expression.

>>> x = Int('x')
>>> y = Int('y')
>>> Distinct(x, y)
x != y
>>> z = Int('z')
>>> Distinct(x, y, z)
Distinct(x, y, z)
>>> simplify(Distinct(x, y, z))
Distinct(x, y, z)
>>> simplify(Distinct(x, y, z), blast_distinct=True)
And(Not(x == y), Not(x == z), Not(y == z))
N5At least one of the arguments must be a Z3 expression)	rd   r2  r   r;   r^  r@  r  r
  rM   rb   rP   r;  r:  s       r   Distinctru    s]     T?D
 
&Czz3d?$[\T'Dd#IE>#'')R7==r   c                    [         S-  " 5       n[        5       (       a#  [        UR                  UR                  :H  S5        UR	                  5       US'   UR	                  5       US'   U " UR                  R                  5       SU5      $ )Nrx   r/  r   r   )r?  r   r;   rP   r   rM   )r  r   r&  rb   s       r   _mk_binrw    sb    !G;Dzz155AEE>#56hhjDGhhjDGQUUYY[!T""r   c           	          [        5       (       a  [        [        U[        5      S5        UR                  n[        [        UR                  5       [        X5      UR                  5      U5      $ )zBCreate a constant of the given sort.

>>> Const('x', IntSort())
x
r  )
r   r;   r   rM  rP   rH  Z3_mk_constrM   rQ   r   )r?   r]  rP   s      r   Constrz    sL     zz:dG,.@A
((CCGGIy/CTXXNPSTTr   c                     [        U [        5      (       a  U R                  S5      n U  Vs/ s H  n[        X!5      PM     sn$ s  snf )zCreate several constants of the given sort.

`names` is a string containing the names of all constants to be created.
Blank spaces separate the names of different constants.

>>> x, y, z = Consts('x y z', IntSort())
>>> x + y + z
x + y + z
 )r   rl   splitrz  )namesr]  r?   s      r   Constsr    s<     %C */0%$E$%000s   Ac                     [        5       (       a!  [        [        U 5      S[        U 5       35        [	        U R
                  5      n[        [        UR                  5       XR                  5      U5      $ )z+Create a fresh constant of a specified sortzZ3 sort expected, got )
r   r;   ru  typerL   rP   rH  Z3_mk_fresh_constrM   r   )r]  prefixrP   s      r   
FreshConstr    sP    zz74=$:4:,"GH
488
C)#'')VXXFLLr   r  c                     [        5       (       a  [        [        U5      S5        [        [	        UR                  5       XR                  5      UR                  5      $ )a
  Create a Z3 free variable. Free variables are used to create quantified formulas.
A free variable with index n is bound when it occurs within the scope of n+1 quantified
declarations.

>>> Var(0, IntSort())
Var(0)
>>> eq(Var(0, IntSort()), Var(0, BoolSort()))
False
r  )r   r;   ru  rH  Z3_mk_boundr   r   rP   )r  rH   s     r   Varr    s<     zz71:12AIIKee<aeeDDr   c                 ,    [        U [        U5      5      $ )z
Create a real free variable. Free variables are used to create quantified formulas.
They are also used to create polynomials.

>>> RealVar(0)
Var(0)
)r  RealSort)r  rP   s     r   RealVarr    s     sHSM""r   r>   c                 V    [        U 5       Vs/ s H  n[        X!5      PM     sn$ s  snf )z
Create a list of Real free variables.
The variables have ids: 0, 1, ..., n-1

>>> x0, x1, x2, x3 = RealVarVector(4)
>>> x2
Var(2)
)r7  r  )r>   rP   r<  s      r   RealVarVectorr    s$     &+1X.XGAOX...s   &c                   0    \ rS rSrSrS rS rS rS rSr	g)	rz  i  zBoolean sort.c                 z   [        U[        5      (       a  [        XR                  5      $ [	        5       (       a  [        U5      (       d$  Sn[        [        U5      X![        U5      4-  5        U R                  UR                  5       5      (       d)  [        U R                  UR                  5       5      S5        U$ )zTry to cast `val` as a Boolean.

>>> x = BoolSort().cast(True)
>>> x
True
>>> is_expr(x)
True
>>> is_expr(True)
False
>>> x.sort()
Bool
zETrue, False or Z3 Boolean expression expected. Received %s of type %sz1Value cannot be converted into a Z3 Boolean value)
r   rk   BoolValrP   r   r\  r;   r  r   r]  )r   rn   r   s      r   r_  BoolSortRef.cast  s     c4  3))::3<<]73<T#Y/?)?@77388:&&477388:.0cd
r   c                 "    [        U[        5      $ r   r   r}  r   s     r   rX  BoolSortRef.subsort4  s    %..r   c                     gr   r   r   s    r   is_intBoolSortRef.is_int7  r   r   c                     gr   r   r   s    r   is_boolBoolSortRef.is_bool:  r   r   r   N)
r   r   r   r   r   r_  rX  r  r  r   r   r   r   rz  rz    s    ./r   rz  c                   T    \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rSrg)r  i>  z4All Boolean expressions are instances of this class.c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ r   )rz  r  r   r   rP   r   s    r   r]  BoolRef.sortA  s&    ;t||~t{{}EtxxPPr   c                 f    [        U[        5      (       a  [        USS5      n[        U SS5      U-   $ rZ   )r   r  rq  r   s     r   __add__BoolRef.__add__D  s/    eW%%uaOE$1~%%r   c                 
    X-   $ r   r   r   s     r   __radd__BoolRef.__radd__I  
    |r   c                 
    X-  $ r   r   r   s     r   __rmul__BoolRef.__rmul__L  r  r   c                    [        U[        5      (       a  US:X  a  [        U SS5      $ [        U[        5      (       a  US:X  a  [        SU R                  5      $ [        U[
        5      (       a  [        USS5      n[        XS5      $ )z1Create the Z3 expression `self * other`.
        r   r   )r   r   rq  IntValrP   r  r   s     r   __mul__BoolRef.__mul__O  sp     eS!!eqjdAq>!eS!!eqj!TXX&&eW%%uaOE$q!!r   c                     [        X5      $ r   )Andr   s     r   __and__BoolRef.__and__Z      4r   c                     [        X5      $ r   )Orr   s     r   __or__BoolRef.__or__]  s    $r   c                     [        X5      $ r   )Xorr   s     r   __xor__BoolRef.__xor__`  r  r   c                     [        U 5      $ r   )Notr   s    r   
__invert__BoolRef.__invert__c  s    4yr   c                 H    [        U 5      (       a  g[        U 5      (       a  gg )NTF)r   r   r   s    r   r"  BoolRef.py_valuef  s    4==D>>r   r   N)r   r   r   r   r   r]  r  r  r  r  r  r  r  r  r"  r   r   r   r   r  r  >  s8    >Q&
	"  r   r  c                 "    [        U [        5      $ )zReturn `True` if `a` is a Z3 Boolean expression.

>>> p = Bool('p')
>>> is_bool(p)
True
>>> q = Bool('q')
>>> is_bool(And(p, q))
True
>>> x = Real('x')
>>> is_bool(x)
False
>>> is_bool(x == 0)
True
)r   r  r%  s    r   r  r  p  s     a!!r   c                 "    [        U [        5      $ )zReturn `True` if `a` is the Z3 true expression.

>>> p = Bool('p')
>>> is_true(p)
False
>>> is_true(simplify(p == p))
True
>>> x = Real('x')
>>> is_true(x == 0)
False
>>> # True is a Python Boolean expression
>>> is_true(True)
False
)rk  
Z3_OP_TRUEr%  s    r   r   r     s     Q
##r   c                 "    [        U [        5      $ )zReturn `True` if `a` is the Z3 false expression.

>>> p = Bool('p')
>>> is_false(p)
False
>>> is_false(False)
False
>>> is_false(BoolVal(False))
True
)rk  Z3_OP_FALSEr%  s    r   r   r     s     Q$$r   c                 "    [        U [        5      $ )z|Return `True` if `a` is a Z3 and expression.

>>> p, q = Bools('p q')
>>> is_and(And(p, q))
True
>>> is_and(Or(p, q))
False
)rk  	Z3_OP_ANDr%  s    r   is_andr         Q	""r   c                 "    [        U [        5      $ )zyReturn `True` if `a` is a Z3 or expression.

>>> p, q = Bools('p q')
>>> is_or(Or(p, q))
True
>>> is_or(And(p, q))
False
)rk  Z3_OP_ORr%  s    r   is_orr         Q!!r   c                 "    [        U [        5      $ )zReturn `True` if `a` is a Z3 implication expression.

>>> p, q = Bools('p q')
>>> is_implies(Implies(p, q))
True
>>> is_implies(And(p, q))
False
)rk  Z3_OP_IMPLIESr%  s    r   
is_impliesr    s     Q&&r   c                 "    [        U [        5      $ )zlReturn `True` if `a` is a Z3 not expression.

>>> p = Bool('p')
>>> is_not(p)
False
>>> is_not(Not(p))
True
)rk  	Z3_OP_NOTr%  s    r   is_notr    r  r   c                 "    [        U [        5      $ )zaReturn `True` if `a` is a Z3 equality expression.

>>> x, y = Ints('x y')
>>> is_eq(x == y)
True
)rk  Z3_OP_EQr%  s    r   r   r     s     Q!!r   c                 "    [        U [        5      $ )zReturn `True` if `a` is a Z3 distinct expression.

>>> x, y, z = Ints('x y z')
>>> is_distinct(x == y)
False
>>> is_distinct(Distinct(x, y, z))
True
)rk  Z3_OP_DISTINCTr%  s    r   is_distinctr    s     Q''r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ )zReturn the Boolean Z3 sort. If `ctx=None`, then the global context is used.

>>> BoolSort()
Bool
>>> p = Const('p', BoolSort())
>>> is_bool(p)
True
>>> r = Function('r', IntSort(), IntSort(), BoolSort())
>>> r(0, 1)
r(0, 1)
>>> is_bool(r(0, 1))
True
)rL   rz  Z3_mk_bool_sortrM   r   s    r   r'  r'    s%     3-Cswwy1377r   c                     [        U5      nU (       a#  [        [        UR                  5       5      U5      $ [        [	        UR                  5       5      U5      $ )zReturn the Boolean value `True` or `False`. If `ctx=None`, then the global context is used.

>>> BoolVal(True)
True
>>> is_true(BoolVal(True))
True
>>> is_true(True)
False
>>> is_false(BoolVal(False))
True
)rL   r  
Z3_mk_truerM   Z3_mk_falsern   rP   s     r   r  r    s@     3-C
z#''),c22{3779-s33r   c           	          [        U5      n[        [        UR                  5       [	        X5      [        U5      R                  5      U5      $ )zReturn a Boolean constant named `name`. If `ctx=None`, then the global context is used.

>>> p = Bool('p')
>>> q = Bool('q')
>>> And(p, q)
And(p, q)
)rL   r  ry  rM   rQ   r'  r   r  s     r   Boolr    s9     3-C;swwy)D*>@Q@QRTWXXr   c                     [        U5      n[        U [        5      (       a  U R                  S5      n U  Vs/ s H  n[	        X!5      PM     sn$ s  snf )zReturn a tuple of Boolean constants.

`names` is a single string containing all names separated by blank spaces.
If `ctx=None`, then the global context is used.

>>> p, q, r = Bools('p q r')
>>> And(p, Or(q, r))
And(p, Or(q, r))
r|  )rL   r   rl   r}  r  r~  rP   r?   s      r   Boolsr    sD     3-C%C (-.DO...   Ac                 d    [        U5       Vs/ s H  n[        U < SU< 35      PM     sn$ s  snf )zReturn a list of Boolean constants of size `sz`.

The constants are named using the given prefix.
If `ctx=None`, then the global context is used.

>>> P = BoolVector('p', 3)
>>> P
[p__0, p__1, p__2]
>>> And(P)
And(p__0, p__1, p__2)
__)r7  r  r  r:  rP   r<  s       r   
BoolVectorr  )  s*     38)<)QDVQ'()<<<s   -c           	          [        U5      n[        [        UR                  5       U [	        U5      R
                  5      U5      $ )zReturn a fresh Boolean constant in the given context using the given prefix.

If `ctx=None`, then the global context is used.

>>> b1 = FreshBool()
>>> b2 = FreshBool()
>>> eq(b1, b2)
False
)rL   r  r  rM   r'  r   r  rP   s     r   	FreshBoolr  8  s4     3-C$SWWY8I8IJCPPr   c                 
   [        [        X/U5      5      n[        U5      nUR                  U 5      n UR                  U5      n[	        [        UR                  5       U R                  5       UR                  5       5      U5      $ )zYCreate a Z3 implies expression.

>>> p, q = Bools('p q')
>>> Implies(p, q)
Implies(p, q)
)rL   r2  r'  r_  r  Z3_mk_impliesrM   r   rT  s       r   Impliesr  F  sc     )1&#6
7CA	q	A	q	A=AHHJ
CSIIr   c                 
   [        [        X/U5      5      n[        U5      nUR                  U 5      n UR                  U5      n[	        [        UR                  5       U R                  5       UR                  5       5      U5      $ )zqCreate a Z3 Xor expression.

>>> p, q = Bools('p q')
>>> Xor(p, q)
Xor(p, q)
>>> simplify(Xor(p, q))
Not(p == q)
)rL   r2  r'  r_  r  	Z3_mk_xorrM   r   rT  s       r   r  r  T  sc     )1&#6
7CA	q	A	q	A9SWWY
AHHJ?EEr   c                 F   [        [        U /U5      5      n[        U 5      (       a.  [        [	        UR                  5       U R                  5      U5      $ [        U5      nUR                  U 5      n [        [        UR                  5       U R                  5       5      U5      $ )zpCreate a Z3 not expression or probe.

>>> p = Bool('p')
>>> Not(Not(p))
Not(Not(p))
>>> simplify(Not(Not(p)))
p
)rL   r2  r0  rm  Z3_probe_notrM   prober'  r_  r  	Z3_mk_notr   )r   rP   rH   s      r   r  r  d  su     )1#s3
4C{{\#'')QWW5s;;SMFF1IyAHHJ7==r   c                 Z    [        U 5      (       a  U R                  S5      $ [        U 5      $ r2   )r  rc   r  r%  s    r   mk_notr  w  s!    ayyuuQx1vr   c                 :    U  H  n[        U5      (       d  M    g   g)zKReturn `True` if one of the elements of the given collection is a Z3 probe.TF)r0  ra   s     r   
_has_prober  ~  s    C==  r   c                     Sn[        U 5      S:  a  U [        U 5      S-
     n[        U[        5      (       a#  U [        U 5      S-
     nU S[        U 5      S-
   n OM[        U 5      S:X  a<  [        U S   [        5      (       a$  U S   R                  nU S    Vs/ s H  o3PM     n nOSn[        U 5      n [        [        X5      5      n[        5       (       a  [        USLS5        [        U 5      (       a  [        X5      $ [        X5      n [        U 5      u  pE[        [        UR!                  5       XT5      U5      $ s  snf )zCreate a Z3 and-expression or and-probe.

>>> p, q, r = Bools('p q r')
>>> And(p, q, r)
And(p, q, r)
>>> P = BoolVector('p', 5)
>>> And(P)
And(p__0, p__1, p__2, p__3, p__4)
Nr   r   >At least one of the arguments must be a Z3 expression or probe)r[   r   ru   r_   rP   rd   rL   r2  r   r;   r  
_probe_andr^  r@  r  	Z3_mk_andrM   rb   last_argrP   r   r;  r:  s         r   r  r    s    H
4y1}D	A&(G$$3t9q=!NSY]#	TaJtAw	::1gkk7#7a7#T?D
)$4
5Czz3d?$de$$$$ +!$'	yB6<< $   D;c                     Sn[        U 5      S:  a  U [        U 5      S-
     n[        U[        5      (       a#  U [        U 5      S-
     nU S[        U 5      S-
   n OM[        U 5      S:X  a<  [        U S   [        5      (       a$  U S   R                  nU S    Vs/ s H  o3PM     n nOSn[        U 5      n [        [        X5      5      n[        5       (       a  [        USLS5        [        U 5      (       a  [        X5      $ [        X5      n [        U 5      u  pE[        [        UR!                  5       XT5      U5      $ s  snf )zCreate a Z3 or-expression or or-probe.

>>> p, q, r = Bools('p q r')
>>> Or(p, q, r)
Or(p, q, r)
>>> P = BoolVector('p', 5)
>>> Or(P)
Or(p__0, p__1, p__2, p__3, p__4)
Nr   r   r  )r[   r   ru   r_   rP   rd   rL   r2  r   r;   r  	_probe_orr^  r@  r  Z3_mk_orrM   r  s         r   r  r    s    H
4y1}D	A&(G$$3t9q=!NSY]#	TaJtAw	::1gkk7#7a7#T?D
)$4
5Czz3d?$de$## +!$'	x	25s;; $r  c                   $    \ rS rSrSrS rS rSrg)r2  i  z6Patterns are hints for quantifier instantiation.

    c                 J    [        U R                  5       U R                  5      $ r   )Z3_pattern_to_astr   r   r   s    r   r   PatternRef.as_ast  s     ::r   c                 R    [        U R                  5       U R                  5       5      $ r   r  r   s    r   r	  PatternRef.get_id  rS  r   r   N)r   r   r   r   r   r   r	  r   r   r   r   r2  r2    s    ;<r   r2  c                 "    [        U [        5      $ )a(  Return `True` if `a` is a Z3 pattern (hint for quantifier instantiation.

>>> f = Function('f', IntSort(), IntSort())
>>> x = Int('x')
>>> q = ForAll(x, f(x) == 0, patterns = [ f(x) ])
>>> q
ForAll(x, f(x) == 0)
>>> q.num_patterns()
1
>>> is_pattern(q.pattern(0))
True
>>> q.pattern(0)
f(Var(0))
)r   r2  r%  s    r   
is_patternr    s     a$$r   c            
      8   [        5       (       aG  [        [        U 5      S:  S5        [        [        U  Vs/ s H  n[	        U5      PM     sn5      S5        U S   R
                  n[        U 5      u  p[        [        UR                  5       X05      U5      $ s  snf )a|  Create a Z3 multi-pattern using the given expressions `*args`

>>> f = Function('f', IntSort(), IntSort())
>>> g = Function('g', IntSort(), IntSort())
>>> x = Int('x')
>>> q = ForAll(x, f(x) != g(x), patterns = [ MultiPattern(f(x), g(x)) ])
>>> q
ForAll(x, f(x) != g(x))
>>> q.num_patterns()
1
>>> is_pattern(q.pattern(0))
True
>>> q.pattern(0)
MultiPattern(f(Var(0)), g(Var(0)))
r   At least one argument expectedzZ3 expressions expected)
r   r;   r[   allr\  rP   r@  r2  Z3_mk_patternrM   )rb   r   rP   r:  s       r   MultiPatternr    sy      zz3t9q="BC3D1Dq
D124MN
q'++CT"HDmCGGIr8#>> 2s   Bc                 <    [        U 5      (       a  U $ [        U 5      $ r   )r  r  rc   s    r   _to_patternr    s    #
C  r   c                       \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rS rS rS rS rS rS rS rS rS rSrg)r4  i  z2Universally and Existentially quantified formulas.c                     U R                   $ r   r  r   s    r   r   QuantifierRef.as_ast  r  r   c                 R    [        U R                  5       U R                  5       5      $ r   r  r   s    r   r	  QuantifierRef.get_id  rS  r   c                     U R                  5       (       a$  [        U R                  U R                  5       5      $ [	        U R                  5      $ )z*Return the Boolean sort or sort of Lambda.)	is_lambdar  rP   r   r'  r   s    r   r]  QuantifierRef.sort  s5    >>4;;=11!!r   c                 J    [        U R                  5       U R                  5      $ )zReturn `True` if `self` is a universal quantifier.

>>> f = Function('f', IntSort(), IntSort())
>>> x = Int('x')
>>> q = ForAll(x, f(x) == 0)
>>> q.is_forall()
True
>>> q = Exists(x, f(x) != 0)
>>> q.is_forall()
False
)Z3_is_quantifier_forallr   r   r   s    r   	is_forallQuantifierRef.is_forall        't||~txx@@r   c                 J    [        U R                  5       U R                  5      $ )zReturn `True` if `self` is an existential quantifier.

>>> f = Function('f', IntSort(), IntSort())
>>> x = Int('x')
>>> q = ForAll(x, f(x) == 0)
>>> q.is_exists()
False
>>> q = Exists(x, f(x) != 0)
>>> q.is_exists()
True
)Z3_is_quantifier_existsr   r   r   s    r   	is_existsQuantifierRef.is_exists.  r  r   c                 J    [        U R                  5       U R                  5      $ )zReturn `True` if `self` is a lambda expression.

>>> f = Function('f', IntSort(), IntSort())
>>> x = Int('x')
>>> q = Lambda(x, f(x))
>>> q.is_lambda()
True
>>> q = Exists(x, f(x) != 0)
>>> q.is_lambda()
False
)Z3_is_lambdar   r   r   s    r   r  QuantifierRef.is_lambda<  s     DLLNDHH55r   c                 j    [        5       (       a  [        U R                  5       S5        [        X5      $ )z.Return the Z3 expression `self[arg]`.
        z(quantifier should be a lambda expression)r   r;   r  _array_selectr   rc   s     r   __getitem__QuantifierRef.__getitem__J  s(     ::t~~')STT''r   c                 \    [        [        U R                  5       U R                  5      5      $ )zReturn the weight annotation of `self`.

>>> f = Function('f', IntSort(), IntSort())
>>> x = Int('x')
>>> q = ForAll(x, f(x) == 0)
>>> q.weight()
1
>>> q = ForAll(x, f(x) == 0, weight=10)
>>> q.weight()
10
)r   Z3_get_quantifier_weightr   r   r   s    r   weightQuantifierRef.weightQ  s!     +DLLNDHHEFFr   c                 r    [        U R                  [        U R                  5       U R                  5      5      $ )z(Return the skolem id of `self`.
        )rX   rP   Z3_get_quantifier_skolem_idr   r   r   s    r   	skolem_idQuantifierRef.skolem_id_  s*     $(($?PTPXPX$YZZr   c                 r    [        U R                  [        U R                  5       U R                  5      5      $ )z,Return the quantifier id of `self`.
        )rX   rP   Z3_get_quantifier_idr   r   r   s    r   qidQuantifierRef.qidd  s'     $(($8$RSSr   c                 \    [        [        U R                  5       U R                  5      5      $ )a  Return the number of patterns (i.e., quantifier instantiation hints) in `self`.

>>> f = Function('f', IntSort(), IntSort())
>>> g = Function('g', IntSort(), IntSort())
>>> x = Int('x')
>>> q = ForAll(x, f(x) != g(x), patterns = [ f(x), g(x) ])
>>> q.num_patterns()
2
)r   Z3_get_quantifier_num_patternsr   r   r   s    r   num_patternsQuantifierRef.num_patternsi  s!     1$,,.$((KLLr   c                     [        5       (       a  [        XR                  5       :  S5        [        [	        U R                  5       U R                  U5      U R                  5      $ )a5  Return a pattern (i.e., quantifier instantiation hints) in `self`.

>>> f = Function('f', IntSort(), IntSort())
>>> g = Function('g', IntSort(), IntSort())
>>> x = Int('x')
>>> q = ForAll(x, f(x) != g(x), patterns = [ f(x), g(x) ])
>>> q.num_patterns()
2
>>> q.pattern(0)
f(Var(0))
>>> q.pattern(1)
g(Var(0))
zInvalid pattern idx)r   r;   r7  r2  Z3_get_quantifier_pattern_astr   r   rP   r  s     r   patternQuantifierRef.patternu  sK     ::s..002GH7RUVX\X`X`aar   c                 J    [        U R                  5       U R                  5      $ )z!Return the number of no-patterns.)!Z3_get_quantifier_num_no_patternsr   r   r   s    r   num_no_patternsQuantifierRef.num_no_patterns  s    0JJr   c                     [        5       (       a  [        XR                  5       :  S5        [        [	        U R                  5       U R                  U5      U R                  5      $ )zReturn a no-pattern.zInvalid no-pattern idx)r   r;   r?  rH   Z3_get_quantifier_no_pattern_astr   r   rP   r  s     r   
no_patternQuantifierRef.no_pattern  sI    ::s11335MN<T\\^TXXWZ[]a]e]effr   c                 r    [        [        U R                  5       U R                  5      U R                  5      $ )zReturn the expression being quantified.

>>> f = Function('f', IntSort(), IntSort())
>>> x = Int('x')
>>> q = ForAll(x, f(x) == 0)
>>> q.body()
f(Var(0)) == 0
)rH  Z3_get_quantifier_bodyr   r   rP   r   s    r   r  QuantifierRef.body  s'     24<<>488LdhhWWr   c                 \    [        [        U R                  5       U R                  5      5      $ )zReturn the number of variables bounded by this quantifier.

>>> f = Function('f', IntSort(), IntSort(), IntSort())
>>> x = Int('x')
>>> y = Int('y')
>>> q = ForAll([x, y], f(x, y) >= x)
>>> q.num_vars()
2
)r   Z3_get_quantifier_num_boundr   r   r   s    r   num_varsQuantifierRef.num_vars  s!     .t||~txxHIIr   c                     [        5       (       a  [        XR                  5       :  S5        [        U R                  [        U R                  5       U R                  U5      5      $ )zReturn a string representing a name used when displaying the quantifier.

>>> f = Function('f', IntSort(), IntSort(), IntSort())
>>> x = Int('x')
>>> y = Int('y')
>>> q = ForAll([x, y], f(x, y) >= x)
>>> q.var_name(0)
'x'
>>> q.var_name(1)
'y'
Invalid variable idx)r   r;   rJ  rX   rP   Z3_get_quantifier_bound_namer   r   r  s     r   var_nameQuantifierRef.var_name  sH     ::s]]_,.DE$(($@QUQYQY[^$_``r   c                     [        5       (       a  [        XR                  5       :  S5        [        [	        U R                  5       U R                  U5      U R                  5      $ )zReturn the sort of a bound variable.

>>> f = Function('f', IntSort(), RealSort(), IntSort())
>>> x = Int('x')
>>> y = Real('y')
>>> q = ForAll([x, y], f(x, y) >= x)
>>> q.var_sort(0)
Int
>>> q.var_sort(1)
Real
rM  )r   r;   rJ  rE  Z3_get_quantifier_bound_sortr   r   rP   r  s     r   var_sortQuantifierRef.var_sort  sH     ::s]]_,.DE8SVWY]YaYabbr   c                 $    U R                  5       /$ )zReturn a list containing a single element self.body()

>>> f = Function('f', IntSort(), IntSort())
>>> x = Int('x')
>>> q = ForAll(x, f(x) == 0)
>>> q.children()
[f(Var(0)) == 0]
)r  r   s    r   r  QuantifierRef.children  s     		}r   r   N)r   r   r   r   r   r   r	  r]  r  r  r  r'  r+  r/  r3  r7  r;  r?  rC  r  rJ  rO  rS  r  r   r   r   r   r4  r4    sq    <<"AA6(G[
T

Mb$Kg	X
Ja c 	r   r4  c                 "    [        U [        5      $ )zReturn `True` if `a` is a Z3 quantifier.

>>> f = Function('f', IntSort(), IntSort())
>>> x = Int('x')
>>> q = ForAll(x, f(x) == 0)
>>> is_quantifier(q)
True
>>> is_quantifier(f(x))
False
)r   r4  r%  s    r   is_quantifierrX    s     a''r    c                    [        5       (       Ga  [        [        U5      =(       d5    [        U5      =(       d#    [	        U5      S:  =(       a    [        US   5      S5        [        [        U5      =(       d:    [	        U5      S:  =(       a%    [        U Vs/ s H  n[        U5      PM     sn5      S5        [        [        U V	s/ s H   n	[        U	5      =(       d    [        U	5      PM"     sn	5      S5        [        [        U V
s/ s H  n
[        U
5      PM     sn
5      S5        [        U5      (       a  UR                  nU/nOUS   R                  n[        U5      (       d  [        X+5      n[	        U5      nUS:X  a  U$ [        U-  " 5       n[        U5       H  nX   R                  5       X'   M     U V
s/ s H  n
[        U
5      PM     nn
[	        U5      n[        U-  " 5       n[        U5       H  nXn   R                   UU'   M     [#        U5      u  nn[%        XK5      n[%        X[5      n['        [)        UR+                  5       XXEXUUUUUR                  5       5      U5      $ s  snf s  sn	f s  sn
f s  sn
f )Nr   r[  zInvalid bounded variable(s)zZ3 patterns expectedzno patterns are Z3 expressions)r   r;   r  r  r[   rc  r
  r  r\  rP   r  r?  r7  r   r  r1  r   r@  rQ   r4  Z3_mk_quantifier_const_exrM   )r  vsr  r+  r3  skidpatternsno_patternsr   r   prP   rJ  _vsr<  num_pats_pats_no_patsnum_no_patss                      r   _mk_quantifierrf    s    zz74=QF2JQ3r7Q;3P6"Q%=Skl8B<SCGaK$RCb8Qb!b8Q4RUrs3XFX
133XFGI_`3K8Kq
K89;[\bzzffTeii4==t!2wH1}>
C8_  )111AH18}Hx"E8_;??a )+6Hk
C
CTD23779iQT3;3;U3>37;;=	B DG	H H3 9RF8 2s   I-'I2I7=I<c           
           [        SXX#XEU5      $ )a  Create a Z3 forall formula.

The parameters `weight`, `qid`, `skid`, `patterns` and `no_patterns` are optional annotations.

>>> f = Function('f', IntSort(), IntSort(), IntSort())
>>> x = Int('x')
>>> y = Int('y')
>>> ForAll([x, y], f(x, y) >= x)
ForAll([x, y], f(x, y) >= x)
>>> ForAll([x, y], f(x, y) >= x, patterns=[ f(x, y) ])
ForAll([x, y], f(x, y) >= x)
>>> ForAll([x, y], f(x, y) >= x, weight=10)
ForAll([x, y], f(x, y) >= x)
Trf  r\  r  r+  r3  r]  r^  r_  s          r   ForAllrj  	  s     $&t{SSr   c           
           [        SXX#XEU5      $ )a  Create a Z3 exists formula.

The parameters `weight`, `qif`, `skid`, `patterns` and `no_patterns` are optional annotations.


>>> f = Function('f', IntSort(), IntSort(), IntSort())
>>> x = Int('x')
>>> y = Int('y')
>>> q = Exists([x, y], f(x, y) >= x, skid="foo")
>>> q
Exists([x, y], f(x, y) >= x)
>>> is_quantifier(q)
True
>>> r = Tactic('nnf')(q).as_expr()
>>> is_quantifier(r)
False
Frh  ri  s          r   Existsrl  	  s    $ %6TTr   c           	      $   UR                   n[        U 5      (       a  U /n [        U 5      n[        U-  " 5       n[	        U5       H  nX   R                  5       XE'   M     [        [        UR                  5       X4UR                  5       5      U5      $ )a#  Create a Z3 lambda expression.

>>> f = Function('f', IntSort(), IntSort(), IntSort())
>>> mem0 = Array('mem0', IntSort(), IntSort())
>>> lo, hi, e, i = Ints('lo hi e i')
>>> mem1 = Lambda([i], If(And(lo <= i, i <= hi), e, mem0[i]))
>>> mem1
Lambda(i, If(And(lo <= i, i <= hi), e, mem0[i]))
)	rP   r  r[   r?  r7  r   r4  Z3_mk_lambda_constrM   )r\  r  rP   rJ  ra  r<  s         r   Lambdaro  ,	  su     ((CbzzT2wH>
C8_  +CGGIxdkkmTVYZZr   c                   6    \ rS rSrSrS rS rS rS rS r	Sr
g	)
r}  iG	  zReal and Integer sorts.c                 0    U R                  5       [        :H  $ )zReturn `True` if `self` is of the sort Real.

>>> x = Real('x')
>>> x.is_real()
True
>>> (x + 1).is_real()
True
>>> x = Int('x')
>>> x.is_real()
False
)rU  r|  r   s    r   is_realArithSortRef.is_realJ	  s     yy{l**r   c                 0    U R                  5       [        :H  $ )zReturn `True` if `self` is of the sort Integer.

>>> x = Int('x')
>>> x.is_int()
True
>>> (x + 1).is_int()
True
>>> x = Real('x')
>>> x.is_int()
False
)rU  r{  r   s    r   r  ArithSortRef.is_intX	  s     yy{k))r   c                     gNFr   r   s    r   r  ArithSortRef.is_boolf	      r   c                 t    U R                  5       =(       a"    [        U5      =(       a    UR                  5       $ )z0Return `True` if `self` is a subsort of `other`.)r  is_arith_sortrr  r   s     r   rX  ArithSortRef.subsorti	  s#    {{}Iu!5I%--/Ir   c                 T   [        U5      (       Ga#  [        5       (       a#  [        U R                  UR                  :H  S5        UR	                  5       nU R                  U5      (       a  U$ UR                  5       (       a   U R                  5       (       a  [        U5      $ UR                  5       (       a"  U R                  5       (       a  [        USS5      $ UR                  5       (       a+  U R                  5       (       a  [        [        USS5      5      $ [        5       (       a  [        SS5        ggU R                  5       (       a  [        XR                  5      $ U R                  5       (       a  [        XR                  5      $ [        5       (       a  Sn[        SX0-  5        gg)zTry to cast `val` as an Integer or Real.

>>> IntSort().cast(10)
10
>>> is_int(IntSort().cast(10))
True
>>> is_int(10)
False
>>> RealSort().cast(10)
10
>>> is_real(RealSort().cast(10))
True
r/  r   r   Fz#Z3 Integer/Real expression expectedzRint, long, float, string (numeral), or Z3 Integer/Real expression expected. Got %sN)r\  r   r;   rP   r]  r   r  rr  ToRealr  rq  r  rS  )r   rn   val_sr   s       r   r_  ArithSortRef.castm	  s    3<<zz488sww.0BCHHJEwwu~~
||~~$,,..c{"}}4;;==#q!}$}}4<<>>bam,,zz5"GH  {{}}c88,,||~~sHH--zzj5#*- r   r   N)r   r   r   r   r   rr  r  r  rX  r_  r   r   r   r   r}  r}  G	  s    !+*J#.r   r}  c                 "    [        U [        5      $ )zReturn `True` if s is an arithmetical sort (type).

>>> is_arith_sort(IntSort())
True
>>> is_arith_sort(RealSort())
True
>>> is_arith_sort(BoolSort())
False
>>> n = Int('x') + 1
>>> is_arith_sort(n.sort())
True
r  rG   s    r   r{  r{  	  s     a&&r   c                       \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rSrg)r7  i	  zInteger and Real expressions.c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ )zwReturn the sort (type) of the arithmetical expression `self`.

>>> Int('x').sort()
Int
>>> (Real('x') + 1).sort()
Real
)r}  r  r   r   rP   r   s    r   r]  ArithRef.sort	  s(     KFQQr   c                 >    U R                  5       R                  5       $ )zReturn `True` if `self` is an integer expression.

>>> x = Int('x')
>>> x.is_int()
True
>>> (x + 1).is_int()
True
>>> y = Real('y')
>>> (x + y).is_int()
False
)r]  r  r   s    r   r  ArithRef.is_int	  s     yy{!!##r   c                 >    U R                  5       R                  5       $ )zrReturn `True` if `self` is an real expression.

>>> x = Real('x')
>>> x.is_real()
True
>>> (x + 1).is_real()
True
)r]  rr  r   s    r   rr  ArithRef.is_real	  s     yy{""$$r   c                 d    [        X5      u  p#[        [        [        X#5      U R                  5      $ )zsCreate the Z3 expression `self + other`.

>>> x = Int('x')
>>> y = Int('y')
>>> x + y
x + y
>>> (x + y).sort()
Int
r  r7  rw  	Z3_mk_addrP   r  s       r   r  ArithRef.__add__	  (     T)	10$((;;r   c                 d    [        X5      u  p#[        [        [        X25      U R                  5      $ )zMCreate the Z3 expression `other + self`.

>>> x = Int('x')
>>> 10 + x
10 + x
r  r  s       r   r  ArithRef.__radd__	  (     T)	10$((;;r   c                     [        U[        5      (       a  [        XS5      $ [        X5      u  p#[	        [        [        X#5      U R                  5      $ )ztCreate the Z3 expression `self * other`.

>>> x = Real('x')
>>> y = Real('y')
>>> x * y
x*y
>>> (x * y).sort()
Real
r   )r   r  rq  r  r7  rw  	Z3_mk_mulrP   r  s       r   r  ArithRef.__mul__	  sB     eW%%e1%%T)	10$((;;r   c                 d    [        X5      u  p#[        [        [        X25      U R                  5      $ )zLCreate the Z3 expression `other * self`.

>>> x = Real('x')
>>> 10 * x
10*x
)r  r7  rw  r  rP   r  s       r   r  ArithRef.__rmul__	  r  r   c                 d    [        X5      u  p#[        [        [        X#5      U R                  5      $ )zsCreate the Z3 expression `self - other`.

>>> x = Int('x')
>>> y = Int('y')
>>> x - y
x - y
>>> (x - y).sort()
Int
r  r7  rw  	Z3_mk_subrP   r  s       r   __sub__ArithRef.__sub__	  r  r   c                 d    [        X5      u  p#[        [        [        X25      U R                  5      $ )zMCreate the Z3 expression `other - self`.

>>> x = Int('x')
>>> 10 - x
10 - x
r  r  s       r   __rsub__ArithRef.__rsub__
  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression `self**other` (** is the power operator).

>>> x = Real('x')
>>> x**3
x**3
>>> (x**3).sort()
Real
>>> simplify(IntVal(2)**8)
256
r  r7  Z3_mk_powerr   r   rP   r  s       r   __pow__ArithRef.__pow__
  <     T)DLLNAHHJ
KTXXVVr   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression `other**self` (** is the power operator).

>>> x = Real('x')
>>> 2**x
2**x
>>> (2**x).sort()
Real
>>> simplify(2**IntVal(8))
256
r  r  s       r   __rpow__ArithRef.__rpow__
  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression `other/self`.

>>> x = Int('x')
>>> y = Int('y')
>>> x/y
x/y
>>> (x/y).sort()
Int
>>> (x/y).sexpr()
'(div x y)'
>>> x = Real('x')
>>> y = Real('y')
>>> x/y
x/y
>>> (x/y).sort()
Real
>>> (x/y).sexpr()
'(/ x y)'
r  r7  	Z3_mk_divr   r   rP   r  s       r   __div__ArithRef.__div__,
  s<    ( T)	$,,.!((*ahhjI488TTr   c                 $    U R                  U5      $ z&Create the Z3 expression `other/self`.r  r   s     r   __truediv__ArithRef.__truediv__C
      ||E""r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression `other/self`.

>>> x = Int('x')
>>> 10/x
10/x
>>> (10/x).sexpr()
'(div 10 x)'
>>> x = Real('x')
>>> 10/x
10/x
>>> (10/x).sexpr()
'(/ 10.0 x)'
r  r  s       r   __rdiv__ArithRef.__rdiv__G
  s<     T)	$,,.!((*ahhjI488TTr   c                 $    U R                  U5      $ r  r  r   s     r   __rtruediv__ArithRef.__rtruediv__X
      }}U##r   c                    [        X5      u  p#[        5       (       a  [        UR                  5       S5        [	        [        U R                  5       UR                  5       UR                  5       5      U R                  5      $ )zCreate the Z3 expression `other%self`.

>>> x = Int('x')
>>> y = Int('y')
>>> x % y
x%y
>>> simplify(IntVal(10) % IntVal(3))
1
Z3 integer expression expected	r  r   r;   r  r7  	Z3_mk_modr   r   rP   r  s       r   __mod__ArithRef.__mod__\
  sT     T)::qxxz#CD	$,,.!((*ahhjI488TTr   c                    [        X5      u  p#[        5       (       a  [        UR                  5       S5        [	        [        U R                  5       UR                  5       UR                  5       5      U R                  5      $ )zICreate the Z3 expression `other%self`.

>>> x = Int('x')
>>> 10 % x
10%x
r  r  r  s       r   __rmod__ArithRef.__rmod__k
  sT     T)::qxxz#CD	$,,.!((*ahhjI488TTr   c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ )z]Return an expression representing `-self`.

>>> x = Int('x')
>>> -x
-x
>>> simplify(-(-x))
x
)r7  Z3_mk_unary_minusr   r   rP   r   s    r   __neg__ArithRef.__neg__w
  s)     )$,,.$++-H$((SSr   c                     U $ )z*Return `self`.

>>> x = Int('x')
>>> +x
x
r   r   s    r   __pos__ArithRef.__pos__
  	     r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression `other <= self`.

>>> x, y = Ints('x y')
>>> x <= y
x <= y
>>> y = Real('y')
>>> x <= y
ToReal(x) <= y
)r  r  Z3_mk_ler   r   rP   r  s       r   __le__ArithRef.__le__
  <     T)x
AHHJGRRr   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )z{Create the Z3 expression `other < self`.

>>> x, y = Ints('x y')
>>> x < y
x < y
>>> y = Real('y')
>>> x < y
ToReal(x) < y
)r  r  Z3_mk_ltr   r   rP   r  s       r   __lt__ArithRef.__lt__
  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )z{Create the Z3 expression `other > self`.

>>> x, y = Ints('x y')
>>> x > y
x > y
>>> y = Real('y')
>>> x > y
ToReal(x) > y
)r  r  Z3_mk_gtr   r   rP   r  s       r   rm  ArithRef.__gt__
  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression `other >= self`.

>>> x, y = Ints('x y')
>>> x >= y
x >= y
>>> y = Real('y')
>>> x >= y
ToReal(x) >= y
)r  r  Z3_mk_ger   r   rP   r  s       r   __ge__ArithRef.__ge__
  r  r   r   N)r   r   r   r   r   r]  r  rr  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rm  r  r   r   r   r   r7  r7  	  s    'R$	%<<<<<<WWU.#U"$U
U	TSSSSr   r7  c                 "    [        U [        5      $ )zReturn `True` if `a` is an arithmetical expression.

>>> x = Int('x')
>>> is_arith(x)
True
>>> is_arith(x + 1)
True
>>> is_arith(1)
False
>>> is_arith(IntVal(1))
True
>>> y = Real('y')
>>> is_arith(y)
True
>>> is_arith(y + 1)
True
)r   r7  r%  s    r   is_arithr  
  s    $ a""r   c                 F    [        U 5      =(       a    U R                  5       $ )zReturn `True` if `a` is an integer expression.

>>> x = Int('x')
>>> is_int(x + 1)
True
>>> is_int(1)
False
>>> is_int(IntVal(1))
True
>>> y = Real('y')
>>> is_int(y)
False
>>> is_int(y + 1)
False
)r  r  r%  s    r   r  r  
  s      A;%188:%r   c                 F    [        U 5      =(       a    U R                  5       $ )zReturn `True` if `a` is a real expression.

>>> x = Int('x')
>>> is_real(x + 1)
False
>>> y = Real('y')
>>> is_real(y)
True
>>> is_real(y + 1)
True
>>> is_real(1)
False
>>> is_real(RealVal(1))
True
)r  rr  r%  s    r   rr  rr  
  s      A;&199;&r   c                 6    [        U R                  5       U5      $ r   )Z3_is_numeral_astrM   r+  s     r   r@  r@  
  s    SWWY**r   c                 6    [        U R                  5       U5      $ r   )Z3_is_algebraic_numberrM   r+  s     r   r9  r9  
  s    !#'')Q//r   c                     [        U 5      =(       a;    U R                  5       =(       a$    [        U R                  U R	                  5       5      $ )a-  Return `True` if `a` is an integer value of sort Int.

>>> is_int_value(IntVal(1))
True
>>> is_int_value(1)
False
>>> is_int_value(Int('x'))
False
>>> n = Int('x') + 1
>>> n
x + 1
>>> n.arg(1)
1
>>> is_int_value(n.arg(1))
True
>>> is_int_value(RealVal("1/3"))
False
>>> is_int_value(RealVal(1))
False
)r  r  r@  rP   r   r%  s    r   is_int_valuer    s/    * A;H188:H+aeeQXXZ*HHr   c                     [        U 5      =(       a;    U R                  5       =(       a$    [        U R                  U R	                  5       5      $ )a?  Return `True` if `a` is rational value of sort Real.

>>> is_rational_value(RealVal(1))
True
>>> is_rational_value(RealVal("3/5"))
True
>>> is_rational_value(IntVal(1))
False
>>> is_rational_value(1)
False
>>> n = Real('x') + 1
>>> n.arg(1)
1
>>> is_rational_value(n.arg(1))
True
>>> is_rational_value(Real('x'))
False
)r  rr  r@  rP   r   r%  s    r   is_rational_valuer    s/    & A;I199;I;quuahhj+IIr   c                     [        U 5      =(       a;    U R                  5       =(       a$    [        U R                  U R	                  5       5      $ )zReturn `True` if `a` is an algebraic value of sort Real.

>>> is_algebraic_value(RealVal("3/5"))
False
>>> n = simplify(Sqrt(2))
>>> n
1.4142135623?
>>> is_algebraic_value(n)
True
)r  rr  r9  rP   r   r%  s    r   is_algebraic_valuer  1  s/     A;K199;K=
+KKr   c                 "    [        U [        5      $ )zReturn `True` if `a` is an expression of the form b + c.

>>> x, y = Ints('x y')
>>> is_add(x + y)
True
>>> is_add(x - y)
False
)rk  	Z3_OP_ADDr%  s    r   is_addr  ?  r  r   c                 "    [        U [        5      $ )zReturn `True` if `a` is an expression of the form b * c.

>>> x, y = Ints('x y')
>>> is_mul(x * y)
True
>>> is_mul(x - y)
False
)rk  	Z3_OP_MULr%  s    r   is_mulr  K  r  r   c                 "    [        U [        5      $ )zReturn `True` if `a` is an expression of the form b - c.

>>> x, y = Ints('x y')
>>> is_sub(x - y)
True
>>> is_sub(x + y)
False
)rk  	Z3_OP_SUBr%  s    r   is_subr  W  r  r   c                 "    [        U [        5      $ )zReturn `True` if `a` is an expression of the form b / c.

>>> x, y = Reals('x y')
>>> is_div(x / y)
True
>>> is_div(x + y)
False
>>> x, y = Ints('x y')
>>> is_div(x / y)
False
>>> is_idiv(x / y)
True
)rk  	Z3_OP_DIVr%  s    r   is_divr  c  s     Q	""r   c                 "    [        U [        5      $ )zReturn `True` if `a` is an expression of the form b div c.

>>> x, y = Ints('x y')
>>> is_idiv(x / y)
True
>>> is_idiv(x + y)
False
)rk  
Z3_OP_IDIVr%  s    r   is_idivr  t  s     Q
##r   c                 "    [        U [        5      $ )zReturn `True` if `a` is an expression of the form b % c.

>>> x, y = Ints('x y')
>>> is_mod(x % y)
True
>>> is_mod(x + y)
False
)rk  	Z3_OP_MODr%  s    r   is_modr    r  r   c                 "    [        U [        5      $ )zReturn `True` if `a` is an expression of the form b <= c.

>>> x, y = Ints('x y')
>>> is_le(x <= y)
True
>>> is_le(x < y)
False
)rk  Z3_OP_LEr%  s    r   is_ler    r  r   c                 "    [        U [        5      $ )zReturn `True` if `a` is an expression of the form b < c.

>>> x, y = Ints('x y')
>>> is_lt(x < y)
True
>>> is_lt(x == y)
False
)rk  Z3_OP_LTr%  s    r   is_ltr     r  r   c                 "    [        U [        5      $ )zReturn `True` if `a` is an expression of the form b >= c.

>>> x, y = Ints('x y')
>>> is_ge(x >= y)
True
>>> is_ge(x == y)
False
)rk  Z3_OP_GEr%  s    r   is_ger    r  r   c                 "    [        U [        5      $ )zReturn `True` if `a` is an expression of the form b > c.

>>> x, y = Ints('x y')
>>> is_gt(x > y)
True
>>> is_gt(x == y)
False
)rk  Z3_OP_GTr%  s    r   is_gtr    r  r   c                 "    [        U [        5      $ )zReturn `True` if `a` is an expression of the form IsInt(b).

>>> x = Real('x')
>>> is_is_int(IsInt(x))
True
>>> is_is_int(x)
False
)rk  Z3_OP_IS_INTr%  s    r   	is_is_intr	    s     Q%%r   c                 "    [        U [        5      $ )zReturn `True` if `a` is an expression of the form ToReal(b).

>>> x = Int('x')
>>> n = ToReal(x)
>>> n
ToReal(x)
>>> is_to_real(n)
True
>>> is_to_real(x)
False
)rk  Z3_OP_TO_REALr%  s    r   
is_to_realr    s     Q&&r   c                 "    [        U [        5      $ )zReturn `True` if `a` is an expression of the form ToInt(b).

>>> x = Real('x')
>>> n = ToInt(x)
>>> n
ToInt(x)
>>> is_to_int(n)
True
>>> is_to_int(x)
False
)rk  Z3_OP_TO_INTr%  s    r   	is_to_intr    s     Q%%r   c                   0    \ rS rSrSrS rS rS rS rSr	g)	r6  i  Integer values.c                     [        5       (       a  [        U R                  5       S5        [        U R	                  5       5      $ )zxReturn a Z3 integer numeral as a Python long (bignum) numeral.

>>> v = IntVal(1)
>>> v + 1
1 + 1
>>> v.as_long() + 1
2
zInteger value expected)r   r;   r  r   	as_stringr   s    r   as_longIntNumRef.as_long  s.     ::t{{}&>?4>>#$$r   c                 R    [        U R                  5       U R                  5       5      $ )z\Return a Z3 integer numeral as a Python string.
>>> v = IntVal(100)
>>> v.as_string()
'100'
Z3_get_numeral_stringr   r   r   s    r   r  IntNumRef.as_string  s     %T\\^T[[]CCr   c                 R    [        U R                  5       U R                  5       5      $ )zjReturn a Z3 integer numeral as a Python binary string.
>>> v = IntVal(10)
>>> v.as_binary_string()
'1010'
Z3_get_numeral_binary_stringr   r   r   s    r   as_binary_stringIntNumRef.as_binary_string  s     ,DLLNDKKMJJr   c                 "    U R                  5       $ r   r  r   s    r   r"  IntNumRef.py_value  s    ||~r   r   N)
r   r   r   r   r   r  r  r  r"  r   r   r   r   r6  r6    s    %DKr   r6  c                   `    \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rS rS rSrg)r8  i
  zRational values.c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ )zReturn the numerator of a Z3 rational numeral.

>>> is_rational_value(RealVal("3/5"))
True
>>> n = RealVal("3/5")
>>> n.numerator()
3
>>> is_rational_value(Q(3,5))
True
>>> Q(3,5).numerator()
3
)r6  Z3_get_numeratorr   r   rP   r   s    r   	numeratorRatNumRef.numerator  s)     )$,,.$++-H$((SSr   c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ )zzReturn the denominator of a Z3 rational numeral.

>>> is_rational_value(Q(3,5))
True
>>> n = Q(3,5)
>>> n.denominator()
5
)r6  Z3_get_denominatorr   r   rP   r   s    r   denominatorRatNumRef.denominator  s)     +DLLNDKKMJDHHUUr   c                 >    U R                  5       R                  5       $ )zReturn the numerator as a Python long.

>>> v = RealVal(10000000000)
>>> v
10000000000
>>> v + 1
10000000000 + 1
>>> v.numerator_as_long() + 1 == 10000000001
True
)r%  r  r   s    r   numerator_as_longRatNumRef.numerator_as_long'  s     ~~''))r   c                 >    U R                  5       R                  5       $ )ziReturn the denominator as a Python long.

>>> v = RealVal("1/3")
>>> v
1/3
>>> v.denominator_as_long()
3
)r)  r  r   s    r   denominator_as_longRatNumRef.denominator_as_long4  s     !))++r   c                     grw  r   r   s    r   r  RatNumRef.is_int?  ry  r   c                     gr   r   r   s    r   rr  RatNumRef.is_realB  r   r   c                 r    U R                  5       R                  5       =(       a    U R                  5       S:H  $ )Nr   )r)  r  r/  r   s    r   r  RatNumRef.is_int_valueE  s-    !((*Nt/G/G/IQ/NNr   c                 V    [        U R                  5       S5        U R                  5       $ )NzExpected integer fraction)r;   r  r,  r   s    r   r  RatNumRef.as_longH  s%    4$$&(CD%%''r   c                 T    [        U R                  5       U R                  5       U5      $ )zReturn a Z3 rational value as a string in decimal notation using at most `prec` decimal places.

>>> v = RealVal("1/5")
>>> v.as_decimal(3)
'0.2'
>>> v = RealVal("1/3")
>>> v.as_decimal(3)
'0.333?'
Z3_get_numeral_decimal_stringr   r   r   precs     r   
as_decimalRatNumRef.as_decimalL       -T\\^T[[]DQQr   c                 R    [        U R                  5       U R                  5       5      $ )zYReturn a Z3 rational numeral as a Python string.

>>> v = Q(3,6)
>>> v.as_string()
'1/2'
r  r   s    r   r  RatNumRef.as_stringX  s     %T\\^T[[]CCr   c                 R    [        U R                  5       U R                  5       5      $ )zmReturn a Z3 rational as a Python Fraction object.

>>> v = RealVal("1/5")
>>> v.as_fraction()
Fraction(1, 5)
)r   r,  r/  r   s    r   as_fractionRatNumRef.as_fractiona  s#     ..0$2J2J2LMMr   c                 R    [        U R                  5       U R                  5       5      $ r   )Z3_get_numeral_doubler   r   r   s    r   r"  RatNumRef.py_valuej      $T\\^T[[]CCr   r   N)r   r   r   r   r   r%  r)  r,  r/  r  rr  r  r  r>  r  rD  r"  r   r   r   r   r8  r8  
  sH    T	V*	,O(
RDNDr   r8  c                   4    \ rS rSrSrS	S jrS rS rS rSr	g)
r:  in  zAlgebraic irrational values.c                 |    [        [        U R                  5       U R                  5       U5      U R                  5      $ )a  Return a Z3 rational number that approximates the algebraic number `self`.
The result `r` is such that |r - self| <= 1/10^precision

>>> x = simplify(Sqrt(2))
>>> x.approx(20)
6838717160008073720548335/4835703278458516698824704
>>> x.approx(5)
2965821/2097152
)r8  Z3_get_algebraic_number_upperr   r   rP   )r   	precisions     r   approxAlgebraicNumRef.approxq  s/     6t||~t{{}V_`bfbjbjkkr   c                 T    [        U R                  5       U R                  5       U5      $ )zReturn a string representation of the algebraic number `self` in decimal notation
using `prec` decimal places.

>>> x = simplify(Sqrt(2))
>>> x.as_decimal(10)
'1.4142135623?'
>>> x.as_decimal(20)
'1.41421356237309504880?'
r:  r<  s     r   r>  AlgebraicNumRef.as_decimal}  r@  r   c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ r   )r_   Z3_algebraic_get_polyr   r   rP   r   s    r   polyAlgebraicNumRef.poly  s'    .t||~t{{}MtxxXXr   c                 R    [        U R                  5       U R                  5       5      $ r   )Z3_algebraic_get_ir   r   r   s    r   indexAlgebraicNumRef.index  s    !$,,.$++-@@r   r   N)
   )
r   r   r   r   r   rN  r>  rT  rX  r   r   r   r   r:  r:  n  s    &
l
RYAr   r:  c                 V   [        U [        5      (       a  [        X5      $ [        U 5      (       a  [	        X5      $ [        U [
        5      (       a  [        X5      $ [        U [        5      (       a  [        X5      $ [        U 5      (       a  U $ [        5       (       a  [        SS5        g g )NFz(Python bool, int, long or float expected)r   rk   r  r   r  rR  rS  rl   rQ  r\  r   r;   r  s     r   rP  rP    s    !Tqqzza~!Uq!S  qzzzz5DE r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ )zReturn the integer sort in the given context. If `ctx=None`, then the global context is used.

>>> IntSort()
Int
>>> x = Const('x', IntSort())
>>> is_int(x)
True
>>> x.sort() == IntSort()
True
>>> x.sort() == BoolSort()
False
)rL   r}  Z3_mk_int_sortrM   r   s    r   IntSortr^    s%     3-Cswwy1377r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ )zReturn the real sort in the given context. If `ctx=None`, then the global context is used.

>>> RealSort()
Real
>>> x = Const('x', RealSort())
>>> is_real(x)
True
>>> is_int(x)
False
>>> x.sort() == RealSort()
True
)rL   r}  Z3_mk_real_sortrM   r   s    r   r  r    s%     3-C	2C88r   c                     [        U [        5      (       a  [        [        U 5      5      $ [        U [        5      (       a	  U (       a  gg[        U 5      $ )N10)r   rR  rl   r   rk   rm   s    r   _to_int_strrd    s<    #u3s8}	C		3xr   c           	          [        U5      n[        [        UR                  5       [	        U 5      [        U5      R                  5      U5      $ )zrReturn a Z3 integer value. If `ctx=None`, then the global context is used.

>>> IntVal(1)
1
>>> IntVal("100")
100
)rL   r6  Z3_mk_numeralrM   rd  r^  r   r  s     r   r  r    s9     3-C]3779k#.>@P@PQSVWWr   c           	          [        U5      n[        [        UR                  5       [	        U 5      [        U5      R                  5      U5      $ )a  Return a Z3 real value.

`val` may be a Python int, long, float or string representing a number in decimal or rational notation.
If `ctx=None`, then the global context is used.

>>> RealVal(1)
1
>>> RealVal(1).sort()
Real
>>> RealVal("3/5")
3/5
>>> RealVal("1.5")
3/2
)rL   r8  rf  rM   rl   r  r   r  s     r   rS  rS    s7     3-C]3779c#h8I8IJCPPr   c                    [        5       (       aX  [        [        U 5      =(       d    [        U [        5      S5        [        [        U5      =(       d    [        U[        5      S5        [        [        X5      [        X5      -  5      $ )z|Return a Z3 rational a/b.

If `ctx=None`, then the global context is used.

>>> RatVal(3,5)
3/5
>>> RatVal(3,5).sort()
Real
z2First argument cannot be converted into an integerz3Second argument cannot be converted into an integer)r   r;   r   r   rl   simplifyrS  r   r&  rP   s      r   RatValrk    sY     zz71:3As!35ij71:3As!35jkGAOgao566r   c                 (    [        [        XUS95      $ )zrReturn a Z3 rational a/b.

If `ctx=None`, then the global context is used.

>>> Q(3,5)
3/5
>>> Q(3,5).sort()
Real
r   )ri  rk  rj  s      r   Qrm    s     F1S)**r   c           	          [        U5      n[        [        UR                  5       [	        X5      [        U5      R                  5      U5      $ )zReturn an integer constant named `name`. If `ctx=None`, then the global context is used.

>>> x = Int('x')
>>> is_int(x)
True
>>> is_int(x + 1)
True
)rL   r7  ry  rM   rQ   r^  r   r  s     r   Intro  	  s9     3-CK	9T+?AQAQRTWXXr   c                     [        U5      n[        U [        5      (       a  U R                  S5      n U  Vs/ s H  n[	        X!5      PM     sn$ s  snf )z]Return a tuple of Integer constants.

>>> x, y, z = Ints('x y z')
>>> Sum(x, y, z)
x + y + z
r|  )rL   r   rl   r}  ro  r  s      r   Intsrq    sD     3-C%C ',-utCNu---r  c                 |    [        U5      n[        U5       Vs/ s H  n[        U < SU< 3U5      PM     sn$ s  snf )zReturn a list of integer constants of size `sz`.

>>> X = IntVector('x', 3)
>>> X
[x__0, x__1, x__2]
>>> Sum(X)
x__0 + x__1 + x__2
r  )rL   r7  ro  r  s       r   	IntVectorrs  #  s5     3-C6;Bi@iCFA&,i@@@   9c           	          [        U5      n[        [        UR                  5       U [	        U5      R
                  5      U5      $ )zReturn a fresh integer constant in the given context using the given prefix.

>>> x = FreshInt()
>>> y = FreshInt()
>>> eq(x, y)
False
>>> x.sort()
Int
)rL   r7  r  rM   r^  r   r  s     r   FreshIntrv  0  s4     3-C%cggi9I9IJCPPr   c           	          [        U5      n[        [        UR                  5       [	        X5      [        U5      R                  5      U5      $ )zReturn a real constant named `name`. If `ctx=None`, then the global context is used.

>>> x = Real('x')
>>> is_real(x)
True
>>> is_real(x + 1)
True
)rL   r7  ry  rM   rQ   r  r   r  s     r   Realrx  >  s9     3-CK	9T+?#ARARSUXYYr   c                     [        U5      n[        U [        5      (       a  U R                  S5      n U  Vs/ s H  n[	        X!5      PM     sn$ s  snf )zxReturn a tuple of real constants.

>>> x, y, z = Reals('x y z')
>>> Sum(x, y, z)
x + y + z
>>> Sum(x, y, z).sort()
Real
r|  )rL   r   rl   r}  rx  r  s      r   Realsrz  K  sD     3-C%C (-.DO...r  c                 |    [        U5      n[        U5       Vs/ s H  n[        U < SU< 3U5      PM     sn$ s  snf )zReturn a list of real constants of size `sz`.

>>> X = RealVector('x', 3)
>>> X
[x__0, x__1, x__2]
>>> Sum(X)
x__0 + x__1 + x__2
>>> Sum(X).sort()
Real
r  )rL   r7  rx  r  s       r   
RealVectorr|  Z  s5     3-C7<RyAy!DVQ'-yAAArt  c           	          [        U5      n[        [        UR                  5       U [	        U5      R
                  5      U5      $ )zReturn a fresh real constant in the given context using the given prefix.

>>> x = FreshReal()
>>> y = FreshReal()
>>> eq(x, y)
False
>>> x.sort()
Real
)rL   r7  r  rM   r  r   r  s     r   	FreshRealr~  i  s4     3-C%cggi#9J9JKSQQr   c                 <   U R                   n[        U [        5      (       a!  [        U [	        SU5      [	        SU5      5      $ [        5       (       a  [        U R                  5       S5        [        [        UR                  5       U R                  5       5      U5      $ )z{Return the Z3 expression ToReal(a).

>>> x = Int('x')
>>> x.sort()
Int
>>> n = ToReal(x)
>>> n
ToReal(x)
>>> n.sort()
Real
r   r   zZ3 integer expression expected.)rP   r   r  rq  rS  r   r;   r  r7  Z3_mk_int2realrM   r   r  s     r   r~  r~  w  sm     %%C!W!WQ_gao66zz188:@AN3779ahhj93??r   c                     [        5       (       a  [        U R                  5       S5        U R                  n[	        [        UR                  5       U R                  5       5      U5      $ )zyReturn the Z3 expression ToInt(a).

>>> x = Real('x')
>>> x.sort()
Real
>>> n = ToInt(x)
>>> n
ToInt(x)
>>> n.sort()
Int
Z3 real expression expected.)r   r;   rr  rP   r7  Z3_mk_real2intrM   r   r  s     r   ToIntr    sE     zz199; >?
%%CN3779ahhj93??r   c                     [        5       (       a  [        U R                  5       S5        U R                  n[	        [        UR                  5       U R                  5       5      U5      $ )zReturn the Z3 predicate IsInt(a).

>>> x = Real('x')
>>> IsInt(x + "1/2")
IsInt(x + 1/2)
>>> solve(IsInt(x + "1/2"), x > 0, x < 1)
[x = 1/2]
>>> solve(IsInt(x + "1/2"), x > 0, x < 1, x != "1/2")
no solution
r  )r   r;   rr  rP   r  Z3_mk_is_intrM   r   r  s     r   IsIntr    sE     zz199; >?
%%C<	188:6<<r   c                 X    [        U 5      (       d  [        U5      n[        X5      n U S-  $ )zfReturn a Z3 expression which represents the square root of a.

>>> x = Real('x')
>>> Sqrt(x)
x**(1/2)
z1/2r\  rL   rS  r  s     r   Sqrtr    )     1::smAO:r   c                 X    [        U 5      (       d  [        U5      n[        X5      n U S-  $ )zeReturn a Z3 expression which represents the cubic root of a.

>>> x = Real('x')
>>> Cbrt(x)
x**(1/3)
z1/3r  r  s     r   Cbrtr    r  r   c                   *    \ rS rSrSrS rS rS rSrg)r  i  zBit-vector sort.c                 \    [        [        U R                  5       U R                  5      5      $ )zhReturn the size (number of bits) of the bit-vector sort `self`.

>>> b = BitVecSort(32)
>>> b.size()
32
)r   Z3_get_bv_sort_sizer   r   r   s    r   sizeBitVecSortRef.size  s!     &t||~txx@AAr   c                 h    [        U5      =(       a!    U R                  5       UR                  5       :  $ r   )
is_bv_sortr  r   s     r   rX  BitVecSortRef.subsort  s#    % ?TYY[5::<%??r   c                     [        U5      (       a4  [        5       (       a#  [        U R                  UR                  :H  S5        U$ [	        X5      $ )zqTry to cast `val` as a Bit-Vector.

>>> b = BitVecSort(32)
>>> b.cast(10)
10
>>> b.cast(10).sexpr()
'#x0000000a'
r/  )r\  r   r;   rP   	BitVecValr^  s     r   r_  BitVecSortRef.cast  s<     3<<zz488sww.0BCJS''r   r   N)	r   r   r   r   r   r  rX  r_  r   r   r   r   r  r    s    B@(r   r  c                 "    [        U [        5      $ )zqReturn True if `s` is a Z3 bit-vector sort.

>>> is_bv_sort(BitVecSort(32))
True
>>> is_bv_sort(IntSort())
False
)r   r  rG   s    r   r  r    s     a''r   c                       \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS r S r!S  r"S! r#S"r$g#)$r<  i  zBit-vector expressions.c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ )zReturn the sort of the bit-vector expression `self`.

>>> x = BitVec('x', 32)
>>> x.sort()
BitVec(32)
>>> x.sort() == BitVecSort(32)
True
)r  r  r   r   rP   r   s    r   r]  BitVecRef.sort  s(     [GRRr   c                 >    U R                  5       R                  5       $ )zReturn the number of bits of the bit-vector expression `self`.

>>> x = BitVec('x', 32)
>>> (x + 1).size()
32
>>> Concat(x, x).size()
64
)r]  r  r   s    r   r  BitVecRef.size  r   r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression `self + other`.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> x + y
x + y
>>> (x + y).sort()
BitVec(32)
r  r<  Z3_mk_bvaddr   r   rP   r  s       r   r  BitVecRef.__add__  <     T)T\\^QXXZLdhhWWr   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zTCreate the Z3 expression `other + self`.

>>> x = BitVec('x', 32)
>>> 10 + x
10 + x
r  r  s       r   r  BitVecRef.__radd__   <     T)T\\^QXXZLdhhWWr   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression `self * other`.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> x * y
x*y
>>> (x * y).sort()
BitVec(32)
r  r<  Z3_mk_bvmulr   r   rP   r  s       r   r  BitVecRef.__mul__*  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zRCreate the Z3 expression `other * self`.

>>> x = BitVec('x', 32)
>>> 10 * x
10*x
r  r  s       r   r  BitVecRef.__rmul__7  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression `self - other`.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> x - y
x - y
>>> (x - y).sort()
BitVec(32)
r  r<  Z3_mk_bvsubr   r   rP   r  s       r   r  BitVecRef.__sub__A  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zTCreate the Z3 expression `other - self`.

>>> x = BitVec('x', 32)
>>> 10 - x
10 - x
r  r  s       r   r  BitVecRef.__rsub__N  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression bitwise-or `self | other`.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> x | y
x | y
>>> (x | y).sort()
BitVec(32)
r  r<  
Z3_mk_bvorr   r   rP   r  s       r   r  BitVecRef.__or__X  s<     T)DLLNAHHJ
KTXXVVr   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )z_Create the Z3 expression bitwise-or `other | self`.

>>> x = BitVec('x', 32)
>>> 10 | x
10 | x
r  r  s       r   __ror__BitVecRef.__ror__e  s<     T)DLLNAHHJ
KTXXVVr   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression bitwise-and `self & other`.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> x & y
x & y
>>> (x & y).sort()
BitVec(32)
r  r<  Z3_mk_bvandr   r   rP   r  s       r   r  BitVecRef.__and__o  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )z_Create the Z3 expression bitwise-or `other & self`.

>>> x = BitVec('x', 32)
>>> 10 & x
10 & x
r  r  s       r   __rand__BitVecRef.__rand__|  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression bitwise-xor `self ^ other`.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> x ^ y
x ^ y
>>> (x ^ y).sort()
BitVec(32)
r  r<  Z3_mk_bvxorr   r   rP   r  s       r   r  BitVecRef.__xor__  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )z`Create the Z3 expression bitwise-xor `other ^ self`.

>>> x = BitVec('x', 32)
>>> 10 ^ x
10 ^ x
r  r  s       r   __rxor__BitVecRef.__rxor__  r  r   c                     U $ )z1Return `self`.

>>> x = BitVec('x', 32)
>>> +x
x
r   r   s    r   r  BitVecRef.__pos__  r  r   c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ )zdReturn an expression representing `-self`.

>>> x = BitVec('x', 32)
>>> -x
-x
>>> simplify(-(-x))
x
)r<  Z3_mk_bvnegr   r   rP   r   s    r   r  BitVecRef.__neg__  (     T\\^T[[]CTXXNNr   c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ )zgCreate the Z3 expression bitwise-not `~self`.

>>> x = BitVec('x', 32)
>>> ~x
~x
>>> simplify(~(~x))
x
)r<  Z3_mk_bvnotr   r   rP   r   s    r   r  BitVecRef.__invert__  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )a  Create the Z3 expression (signed) division `self / other`.

Use the function UDiv() for unsigned division.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> x / y
x/y
>>> (x / y).sort()
BitVec(32)
>>> (x / y).sexpr()
'(bvsdiv x y)'
>>> UDiv(x, y).sexpr()
'(bvudiv x y)'
r  r<  Z3_mk_bvsdivr   r   rP   r  s       r   r  BitVecRef.__div__  s<      T)dllnahhj!((*MtxxXXr   c                 $    U R                  U5      $ )z:Create the Z3 expression (signed) division `self / other`.r  r   s     r   r  BitVecRef.__truediv__  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression (signed) division `other / self`.

Use the function UDiv() for unsigned division.

>>> x = BitVec('x', 32)
>>> 10 / x
10/x
>>> (10 / x).sexpr()
'(bvsdiv #x0000000a x)'
>>> UDiv(10, x).sexpr()
'(bvudiv #x0000000a x)'
r  r  s       r   r  BitVecRef.__rdiv__  s<     T)dllnahhj!((*MtxxXXr   c                 $    U R                  U5      $ )z:Create the Z3 expression (signed) division `other / self`.r  r   s     r   r  BitVecRef.__rtruediv__  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )aT  Create the Z3 expression (signed) mod `self % other`.

Use the function URem() for unsigned remainder, and SRem() for signed remainder.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> x % y
x%y
>>> (x % y).sort()
BitVec(32)
>>> (x % y).sexpr()
'(bvsmod x y)'
>>> URem(x, y).sexpr()
'(bvurem x y)'
>>> SRem(x, y).sexpr()
'(bvsrem x y)'
r  r<  Z3_mk_bvsmodr   r   rP   r  s       r   r  BitVecRef.__mod__  s<    $ T)dllnahhj!((*MtxxXXr   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )a>  Create the Z3 expression (signed) mod `other % self`.

Use the function URem() for unsigned remainder, and SRem() for signed remainder.

>>> x = BitVec('x', 32)
>>> 10 % x
10%x
>>> (10 % x).sexpr()
'(bvsmod #x0000000a x)'
>>> URem(10, x).sexpr()
'(bvurem #x0000000a x)'
>>> SRem(10, x).sexpr()
'(bvsrem #x0000000a x)'
r  r  s       r   r  BitVecRef.__rmod__  s<     T)dllnahhj!((*MtxxXXr   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression (signed) `other <= self`.

Use the function ULE() for unsigned less than or equal to.

>>> x, y = BitVecs('x y', 32)
>>> x <= y
x <= y
>>> (x <= y).sexpr()
'(bvsle x y)'
>>> ULE(x, y).sexpr()
'(bvule x y)'
)r  r  Z3_mk_bvsler   r   rP   r  s       r   r  BitVecRef.__le__  <     T){4<<>188:qxxzJDHHUUr   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression (signed) `other < self`.

Use the function ULT() for unsigned less than.

>>> x, y = BitVecs('x y', 32)
>>> x < y
x < y
>>> (x < y).sexpr()
'(bvslt x y)'
>>> ULT(x, y).sexpr()
'(bvult x y)'
)r  r  Z3_mk_bvsltr   r   rP   r  s       r   r  BitVecRef.__lt__  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression (signed) `other > self`.

Use the function UGT() for unsigned greater than.

>>> x, y = BitVecs('x y', 32)
>>> x > y
x > y
>>> (x > y).sexpr()
'(bvsgt x y)'
>>> UGT(x, y).sexpr()
'(bvugt x y)'
)r  r  Z3_mk_bvsgtr   r   rP   r  s       r   rm  BitVecRef.__gt__.  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression (signed) `other >= self`.

Use the function UGE() for unsigned greater than or equal to.

>>> x, y = BitVecs('x y', 32)
>>> x >= y
x >= y
>>> (x >= y).sexpr()
'(bvsge x y)'
>>> UGE(x, y).sexpr()
'(bvuge x y)'
)r  r  Z3_mk_bvsger   r   rP   r  s       r   r  BitVecRef.__ge__>  r  r   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )a  Create the Z3 expression (arithmetical) right shift `self >> other`

Use the function LShR() for the right logical shift

>>> x, y = BitVecs('x y', 32)
>>> x >> y
x >> y
>>> (x >> y).sexpr()
'(bvashr x y)'
>>> LShR(x, y).sexpr()
'(bvlshr x y)'
>>> BitVecVal(4, 3)
4
>>> BitVecVal(4, 3).as_signed_long()
-4
>>> simplify(BitVecVal(4, 3) >> 1).as_signed_long()
-2
>>> simplify(BitVecVal(4, 3) >> 1)
6
>>> simplify(LShR(BitVecVal(4, 3), 1))
2
>>> simplify(BitVecVal(2, 3) >> 1)
1
>>> simplify(LShR(BitVecVal(2, 3), 1))
1
r  r<  Z3_mk_bvashrr   r   rP   r  s       r   
__rshift__BitVecRef.__rshift__N  s<    6 T)dllnahhj!((*MtxxXXr   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression left shift `self << other`

>>> x, y = BitVecs('x y', 32)
>>> x << y
x << y
>>> (x << y).sexpr()
'(bvshl x y)'
>>> simplify(BitVecVal(2, 3) << 1)
4
r  r<  Z3_mk_bvshlr   r   rP   r  s       r   
__lshift__BitVecRef.__lshift__l  <     T)T\\^QXXZLdhhWWr   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression (arithmetical) right shift `other` >> `self`.

Use the function LShR() for the right logical shift

>>> x = BitVec('x', 32)
>>> 10 >> x
10 >> x
>>> (10 >> x).sexpr()
'(bvashr #x0000000a x)'
r  r  s       r   __rrshift__BitVecRef.__rrshift__z  s<     T)dllnahhj!((*MtxxXXr   c                     [        X5      u  p#[        [        U R                  5       UR	                  5       UR	                  5       5      U R
                  5      $ )zCreate the Z3 expression left shift `other << self`.

Use the function LShR() for the right logical shift

>>> x = BitVec('x', 32)
>>> 10 << x
10 << x
>>> (10 << x).sexpr()
'(bvshl #x0000000a x)'
r  r  s       r   __rlshift__BitVecRef.__rlshift__  r  r   r   N)%r   r   r   r   r   r]  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rm  r  r  r  r  r  r   r   r   r   r<  r<    s    !	S	"XXXXXXWWXXXX	O	OY&#Y $Y*Y$V V V V Y<XYXr   r<  c                   6    \ rS rSrSrS rS rS rS rS r	Sr
g	)
r;  i  zBit-vector values.c                 4    [        U R                  5       5      $ )zReturn a Z3 bit-vector numeral as a Python long (bignum) numeral.

>>> v = BitVecVal(0xbadc0de, 32)
>>> v
195936478
>>> print("0x%.8x" % v.as_long())
0x0badc0de
r   r  r   s    r   r  BitVecNumRef.as_long  s     4>>#$$r   c                     U R                  5       nU R                  5       nUSUS-
  -  :  a  USU-  -
  nUSUS-
  -  * :  a  USU-  -   n[        U5      $ )aP  Return a Z3 bit-vector numeral as a Python long (bignum) numeral.
The most significant bit is assumed to be the sign.

>>> BitVecVal(4, 3).as_signed_long()
-4
>>> BitVecVal(7, 3).as_signed_long()
-1
>>> BitVecVal(3, 3).as_signed_long()
3
>>> BitVecVal(2**32 - 1, 32).as_signed_long()
-1
>>> BitVecVal(2**64 - 1, 64).as_signed_long()
-1
rx   r   )r  r  r   )r   r:  rn   s      r   as_signed_longBitVecNumRef.as_signed_long  s_     YY[lln!b1f+2+C!b1f+2+C3xr   c                 R    [        U R                  5       U R                  5       5      $ r   r  r   s    r   r  BitVecNumRef.as_string  rI  r   c                 R    [        U R                  5       U R                  5       5      $ r   r  r   s    r   r  BitVecNumRef.as_binary_string  s    +DLLNDKKMJJr   c                 "    U R                  5       $ )z3Return the Python value of a Z3 bit-vector numeral.r   r   s    r   r"  BitVecNumRef.py_value  s    ||~r   r   N)r   r   r   r   r   r  r  r  r  r"  r   r   r   r   r;  r;    s     	%.DKr   r;  c                 "    [        U [        5      $ )zReturn `True` if `a` is a Z3 bit-vector expression.

>>> b = BitVec('b', 32)
>>> is_bv(b)
True
>>> is_bv(b + 10)
True
>>> is_bv(Int('x'))
False
)r   r<  r%  s    r   is_bvr    s     a##r   c                 n    [        U 5      =(       a$    [        U R                  U R                  5       5      $ )zReturn `True` if `a` is a Z3 bit-vector numeral value.

>>> b = BitVec('b', 32)
>>> is_bv_value(b)
False
>>> b = BitVecVal(10, 32)
>>> b
10
>>> is_bv_value(b)
True
)r  r@  rP   r   r%  s    r   is_bv_valuer    s$     86AEE188:66r   c                     [        5       (       a  [        [        U 5      S5        U R                  n[	        [        UR                  5       U R                  5       U5      U5      $ )a8  Return the Z3 expression BV2Int(a).

>>> b = BitVec('b', 3)
>>> BV2Int(b).sort()
Int
>>> x = Int('x')
>>> x > BV2Int(b)
x > BV2Int(b)
>>> x > BV2Int(b, is_signed=False)
x > BV2Int(b)
>>> x > BV2Int(b, is_signed=True)
x > If(b < 0, BV2Int(b) - 8, BV2Int(b))
>>> solve(x > BV2Int(b), b == 1, x < 3)
[x = 2, b = 1]
1First argument must be a Z3 bit-vector expression)r   r;   r  rP   r7  Z3_mk_bv2intrM   r   )r   	is_signedrP   s      r   BV2Intr    sE      zz58PQ
%%CLAHHJ	BCHHr   c                 ~    U R                   n[        [        UR                  5       XR	                  5       5      U5      $ )zReturn the z3 expression Int2BV(a, num_bits).
It is a bit-vector of width num_bits and represents the
modulo of a by 2^num_bits
)rP   r<  Z3_mk_int2bvrM   r   )r   num_bitsrP   s      r   Int2BVr    s-    
 %%C\#'')XxxzBCHHr   c                 `    [        U5      n[        [        UR                  5       U 5      U5      $ )zReturn a Z3 bit-vector sort of the given size. If `ctx=None`, then the global context is used.

>>> Byte = BitVecSort(8)
>>> Word = BitVecSort(16)
>>> Byte
BitVec(8)
>>> x = Const('x', Byte)
>>> eq(x, BitVec('x', 8))
True
)rL   r  Z3_mk_bv_sortrM   )r:  rP   s     r   
BitVecSortr    s'     3-Cswwy"5s;;r   c           
      B   [        U5      (       aD  UR                  n[        [        UR	                  5       [        U 5      UR                  5      U5      $ [        U5      n[        [        UR	                  5       [        U 5      [        X5      R                  5      U5      $ )zReturn a bit-vector value with the given number of bits. If `ctx=None`, then the global context is used.

>>> v = BitVecVal(10, 32)
>>> v
10
>>> print("0x%.8x" % v.as_long())
0x0000000a
)	r  rP   r;  rf  rM   rd  r   rL   r  )rn   bvrP   s      r   r  r    ss     "~~ffM#'')[5ErvvNPSTTsmM#'')[5EzRTGZG^G^_adeer   c           	          [        U[        5      (       a  UR                  nO[        U5      n[	        X5      n[        [        UR                  5       [        X5      UR                  5      U5      $ )a,  Return a bit-vector constant named `name`. `bv` may be the number of bits of a bit-vector sort.
If `ctx=None`, then the global context is used.

>>> x  = BitVec('x', 16)
>>> is_bv(x)
True
>>> x.size()
16
>>> x.sort()
BitVec(16)
>>> word = BitVecSort(16)
>>> x2 = BitVec('x', word)
>>> eq(x, x2)
True
)
r   r  rP   rL   r  r<  ry  rM   rQ   r   )r?   r  rP   s      r   BitVecr  %  sR      "m$$ffsm [Id,@"&&I3OOr   c                     [        U5      n[        U [        5      (       a  U R                  S5      n U  Vs/ s H  n[	        X1U5      PM     sn$ s  snf )zReturn a tuple of bit-vector constants of size bv.

>>> x, y, z = BitVecs('x y z', 16)
>>> x.size()
16
>>> x.sort()
BitVec(16)
>>> Sum(x, y, z)
0 + x + y + z
>>> Product(x, y, z)
1*x*y*z
>>> simplify(Product(x, y, z))
x*y*z
r|  )rL   r   rl   r}  r  )r~  r  rP   r?   s       r   BitVecsr!  =  sG     3-C%C .34edF4S!e444   Ac            
      .   [        U 5      n [        U 5      n[        5       (       a  [        US:  S5        SnU  H!  n[	        U5      (       d  M  UR
                  n  O   [        U S   5      (       d  [        U S   [        5      (       a  U  Vs/ s H  n[        XB5      PM     n n[        5       (       a/  [        [        U  Vs/ s H  n[        U5      PM     sn5      S5        [        U-  " 5       n[        U5       H  nX   R                  5       XV'   M     [        [        UR!                  5       X5      U5      $ [#        U S   5      (       a  [        5       (       a/  [        [        U  Vs/ s H  n[#        U5      PM     sn5      S5        [        U-  " 5       n[        U5       H  nX   R                  5       XV'   M     [%        ['        UR!                  5       X5      U5      $ [        5       (       a/  [        [        U  Vs/ s H  n[)        U5      PM     sn5      S5        U S   n[        US-
  5       HI  n[+        [-        UR!                  5       UR                  5       XS-      R                  5       5      U5      nMK     U$ s  snf s  snf s  snf s  snf )	zCreate a Z3 bit-vector concatenation expression.

>>> v = BitVecVal(1, 4)
>>> Concat(v, v+1, v)
Concat(Concat(1, 1 + 1), 1)
>>> simplify(Concat(v, v+1, v))
289
>>> print("%.3x" % simplify(Concat(v, v+1, v)).as_long())
121
rx   z At least two arguments expected.Nr   z+All arguments must be sequence expressions.*All arguments must be regular expressions.z0All arguments must be Z3 bit-vector expressions.r   )rd   r[   r   r;   r\  rP   is_seqr   rl   _coerce_seqr
  r?  r7  r   rF  Z3_mk_seq_concatrM   is_rerH  Z3_mk_re_concatr  r<  Z3_mk_concat)rb   r:  rP   r   rH   r   r<  r   s           r   Concatr+  R  s    T?D	TBzz27>?
C1::%%C  d1g*T!Wc22-12TA#T2::st4t!F1It457de2XLrA7>>#AD &swwy"8#>>T!W~~::sd3dE!Hd346bc2XLrA7>>#AD _SWWY6<<zz3$/$Qa$/02deQA26]l3779ahhj$1u+:L:L:NOQTU H+ 34 4 0s   JJ*J Jc           	         [        U [        5      (       a  [        U 5      n [        U 5      (       at  U n[	        XUR
                  5      u  pE[        [        UR                  5       UR                  5       UR                  5       UR                  5       5      UR
                  5      $ [        5       (       ab  [        X:*  S5        [        [        U 5      =(       a#    U S:  =(       a    [        U5      =(       a    US:  S5        [        [        U5      S5        [        [        UR                  5       XUR                  5       5      UR
                  5      $ )a  Create a Z3 bit-vector extraction expression or sequence extraction expression.

Extract is overloaded to work with both bit-vectors and sequences:

**Bit-vector extraction**: Extract(high, low, bitvector)
    Extracts bits from position `high` down to position `low` (both inclusive).
    - high: int - the highest bit position to extract (0-indexed from right)
    - low: int - the lowest bit position to extract (0-indexed from right)  
    - bitvector: BitVecRef - the bit-vector to extract from
    Returns a new bit-vector containing bits [high:low]

**Sequence extraction**: Extract(sequence, offset, length)
    Extracts a subsequence starting at the given offset with the specified length.
    The functions SubString and SubSeq are redirected to this form of Extract.
    - sequence: SeqRef or str - the sequence to extract from
    - offset: int - the starting position (0-indexed)
    - length: int - the number of elements to extract
    Returns a new sequence containing the extracted subsequence

>>> # Bit-vector extraction examples
>>> x = BitVec('x', 8)
>>> Extract(6, 2, x)  # Extract bits 6 down to 2 (5 bits total)
Extract(6, 2, x)
>>> Extract(6, 2, x).sort()  # Result is a 5-bit vector
BitVec(5)
>>> Extract(7, 0, x)  # Extract all 8 bits
Extract(7, 0, x)
>>> Extract(3, 3, x)  # Extract single bit at position 3
Extract(3, 3, x)

>>> # Sequence extraction examples  
>>> s = StringVal("hello")
>>> Extract(s, 1, 3)  # Extract 3 characters starting at position 1
str.substr("hello", 1, 3)
>>> simplify(Extract(StringVal("abcd"), 2, 1))  # Extract 1 character at position 2
"c"
>>> simplify(Extract(StringVal("abcd"), 0, 2))  # Extract first 2 characters  
"ab"
z?First argument must be greater than or equal to second argumentr   z8First and second arguments must be non negative integersz1Third argument must be a Z3 bit-vector expression)r   rl   rQ  r%  r  rP   rF  Z3_mk_seq_extractr   r   r   r;   r   r  r<  Z3_mk_extract)highlowr   rH   offsetlengths         r   Extractr3    s    P $d||&squu5'		QXXZRXR_R_Rabdedidijjzz3; ab74=LTQYL73<LC1HM	O58PQ]199;188:FNNr   c                 r    [        5       (       a(  [        [        U 5      =(       d    [        U5      S5        g g )Nz;First or second argument must be a Z3 bit-vector expression)r   r;   r  r(  s     r   _check_bv_argsr5    s&    zz58'uQx)fg r   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )zCreate the Z3 expression (unsigned) `other <= self`.

Use the operator <= for signed less than or equal to.

>>> x, y = BitVecs('x y', 32)
>>> ULE(x, y)
ULE(x, y)
>>> (x <= y).sexpr()
'(bvsle x y)'
>>> ULE(x, y).sexpr()
'(bvule x y)'
)r5  r  r  Z3_mk_bvuler   r   rP   r(  s     r   ULEr8    D     1DA;qyy{AHHJ
CQUUKKr   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )zCreate the Z3 expression (unsigned) `other < self`.

Use the operator < for signed less than.

>>> x, y = BitVecs('x y', 32)
>>> ULT(x, y)
ULT(x, y)
>>> (x < y).sexpr()
'(bvslt x y)'
>>> ULT(x, y).sexpr()
'(bvult x y)'
)r5  r  r  Z3_mk_bvultr   r   rP   r(  s     r   ULTr<    r9  r   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )zCreate the Z3 expression (unsigned) `other >= self`.

Use the operator >= for signed greater than or equal to.

>>> x, y = BitVecs('x y', 32)
>>> UGE(x, y)
UGE(x, y)
>>> (x >= y).sexpr()
'(bvsge x y)'
>>> UGE(x, y).sexpr()
'(bvuge x y)'
)r5  r  r  Z3_mk_bvuger   r   rP   r(  s     r   UGEr?    r9  r   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )zCreate the Z3 expression (unsigned) `other > self`.

Use the operator > for signed greater than.

>>> x, y = BitVecs('x y', 32)
>>> UGT(x, y)
UGT(x, y)
>>> (x > y).sexpr()
'(bvsgt x y)'
>>> UGT(x, y).sexpr()
'(bvugt x y)'
)r5  r  r  Z3_mk_bvugtr   r   rP   r(  s     r   UGTrB    r9  r   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )a  Create the Z3 expression (unsigned) division `self / other`.

Use the operator / for signed division.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> UDiv(x, y)
UDiv(x, y)
>>> UDiv(x, y).sort()
BitVec(32)
>>> (x / y).sexpr()
'(bvsdiv x y)'
>>> UDiv(x, y).sexpr()
'(bvudiv x y)'
)r5  r  r<  Z3_mk_bvudivr   r   rP   r(  s     r   UDivrE    D      1DA\!))+qxxz188:FNNr   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )a<  Create the Z3 expression (unsigned) remainder `self % other`.

Use the operator % for signed modulus, and SRem() for signed remainder.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> URem(x, y)
URem(x, y)
>>> URem(x, y).sort()
BitVec(32)
>>> (x % y).sexpr()
'(bvsmod x y)'
>>> URem(x, y).sexpr()
'(bvurem x y)'
)r5  r  r<  Z3_mk_bvuremr   r   rP   r(  s     r   URemrI    rF  r   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )a+  Create the Z3 expression signed remainder.

Use the operator % for signed modulus, and URem() for unsigned remainder.

>>> x = BitVec('x', 32)
>>> y = BitVec('y', 32)
>>> SRem(x, y)
SRem(x, y)
>>> SRem(x, y).sort()
BitVec(32)
>>> (x % y).sexpr()
'(bvsmod x y)'
>>> SRem(x, y).sexpr()
'(bvsrem x y)'
)r5  r  r<  Z3_mk_bvsremr   r   rP   r(  s     r   SRemrL  -  rF  r   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )a  Create the Z3 expression logical right shift.

Use the operator >> for the arithmetical right shift.

>>> x, y = BitVecs('x y', 32)
>>> LShR(x, y)
LShR(x, y)
>>> (x >> y).sexpr()
'(bvashr x y)'
>>> LShR(x, y).sexpr()
'(bvlshr x y)'
>>> BitVecVal(4, 3)
4
>>> BitVecVal(4, 3).as_signed_long()
-4
>>> simplify(BitVecVal(4, 3) >> 1).as_signed_long()
-2
>>> simplify(BitVecVal(4, 3) >> 1)
6
>>> simplify(LShR(BitVecVal(4, 3), 1))
2
>>> simplify(BitVecVal(2, 3) >> 1)
1
>>> simplify(LShR(BitVecVal(2, 3), 1))
1
)r5  r  r<  Z3_mk_bvlshrr   r   rP   r(  s     r   LShRrO  B  sD    6 1DA\!))+qxxz188:FNNr   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )zReturn an expression representing `a` rotated to the left `b` times.

>>> a, b = BitVecs('a b', 16)
>>> RotateLeft(a, b)
RotateLeft(a, b)
>>> simplify(RotateLeft(a, 0))
a
>>> simplify(RotateLeft(a, 16))
a
)r5  r  r<  Z3_mk_ext_rotate_leftr   r   rP   r(  s     r   
RotateLeftrR  b  sH     1DA*199;
AHHJOQRQVQVWWr   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )zReturn an expression representing `a` rotated to the right `b` times.

>>> a, b = BitVecs('a b', 16)
>>> RotateRight(a, b)
RotateRight(a, b)
>>> simplify(RotateRight(a, 0))
a
>>> simplify(RotateRight(a, 16))
a
)r5  r  r<  Z3_mk_ext_rotate_rightr   r   rP   r(  s     r   RotateRightrU  r  sH     1DA+AIIKQXXZPRSRWRWXXr   c                     [        5       (       a*  [        [        U 5      S5        [        [        U5      S5        [	        [        UR                  5       XR                  5       5      UR                  5      $ )a3  Return a bit-vector expression with `n` extra sign-bits.

>>> x = BitVec('x', 16)
>>> n = SignExt(8, x)
>>> n.size()
24
>>> n
SignExt(8, x)
>>> n.sort()
BitVec(24)
>>> v0 = BitVecVal(2, 2)
>>> v0
2
>>> v0.size()
2
>>> v  = simplify(SignExt(6, v0))
>>> v
254
>>> v.size()
8
>>> print("%.x" % v.as_long())
fe
!First argument must be an integer2Second argument must be a Z3 bit-vector expression)	r   r;   r   r  r<  Z3_mk_sign_extr   r   rP   r>   r   s     r   SignExtr[    sM    0 zz71:BC58QR^AIIKHHJ?GGr   c                     [        5       (       a*  [        [        U 5      S5        [        [        U5      S5        [	        [        UR                  5       XR                  5       5      UR                  5      $ )a  Return a bit-vector expression with `n` extra zero-bits.

>>> x = BitVec('x', 16)
>>> n = ZeroExt(8, x)
>>> n.size()
24
>>> n
ZeroExt(8, x)
>>> n.sort()
BitVec(24)
>>> v0 = BitVecVal(2, 2)
>>> v0
2
>>> v0.size()
2
>>> v  = simplify(ZeroExt(6, v0))
>>> v
2
>>> v.size()
8
rW  rX  )	r   r;   r   r  r<  Z3_mk_zero_extr   r   rP   rZ  s     r   ZeroExtr^    sM    , zz71:BC58QR^AIIKHHJ?GGr   c                     [        5       (       a*  [        [        U 5      S5        [        [        U5      S5        [	        [        UR                  5       XR                  5       5      UR                  5      $ )a'  Return an expression representing `n` copies of `a`.

>>> x = BitVec('x', 8)
>>> n = RepeatBitVec(4, x)
>>> n
RepeatBitVec(4, x)
>>> n.size()
32
>>> v0 = BitVecVal(10, 4)
>>> print("%.x" % v0.as_long())
a
>>> v = simplify(RepeatBitVec(4, v0))
>>> v.size()
16
>>> print("%.x" % v.as_long())
aaaa
rW  rX  )	r   r;   r   r  r<  Z3_mk_repeatr   r   rP   rZ  s     r   RepeatBitVecra    sM    $ zz71:BC58QR\!))+q((*=quuEEr   c                     [        5       (       a  [        [        U 5      S5        [        [	        U R                  5       U R                  5       5      U R                  5      $ )z+Return the reduction-and expression of `a`.r  )r   r;   r  r<  Z3_mk_bvredandr   r   rP   r%  s    r   BVRedAndrd    s<    zz58PQ^AIIK<aeeDDr   c                     [        5       (       a  [        [        U 5      S5        [        [	        U R                  5       U R                  5       5      U R                  5      $ )z*Return the reduction-or expression of `a`.r  )r   r;   r  r<  Z3_mk_bvredorr   r   rP   r%  s    r   BVRedOrrg    s<    zz58PQ]199;
;QUUCCr   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       U5      U R                  5      $ )zEA predicate the determines that bit-vector addition does not overflow)r5  r  r  Z3_mk_bvadd_no_overflowr   r   rP   r   r&  signeds      r   BVAddNoOverflowrl    I    1DA*199;
AHHJPVWYZY^Y^__r   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )zMA predicate the determines that signed bit-vector addition does not underflow)r5  r  r  Z3_mk_bvadd_no_underflowr   r   rP   r(  s     r   BVAddNoUnderflowrp    F    1DA+AIIKQXXZPRSRWRWXXr   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )zHA predicate the determines that bit-vector subtraction does not overflow)r5  r  r  Z3_mk_bvsub_no_overflowr   r   rP   r(  s     r   BVSubNoOverflowrt    sF    1DA*199;
AHHJOQRQVQVWWr   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       U5      U R                  5      $ )zIA predicate the determines that bit-vector subtraction does not underflow)r5  r  r  Z3_mk_bvsub_no_underflowr   r   rP   rj  s      r   BVSubNoUnderflowrw    sI    1DA+AIIKQXXZQWXZ[Z_Z_``r   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )zLA predicate the determines that bit-vector signed division does not overflow)r5  r  r  Z3_mk_bvsdiv_no_overflowr   r   rP   r(  s     r   BVSDivNoOverflowrz    rq  r   c                     [        5       (       a  [        [        U 5      S5        [        [	        U R                  5       U R                  5       5      U R                  5      $ )zKA predicate the determines that bit-vector unary negation does not overflowr  )r   r;   r  r  Z3_mk_bvneg_no_overflowr   r   rP   r%  s    r   BVSNegNoOverflowr}    s=    zz58PQ*199;
CQUUKKr   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       U5      U R                  5      $ )zKA predicate the determines that bit-vector multiplication does not overflow)r5  r  r  Z3_mk_bvmul_no_overflowr   r   rP   rj  s      r   BVMulNoOverflowr    rm  r   c                     [        X5        [        X5      u  p[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )zSA predicate the determines that bit-vector signed multiplication does not underflow)r5  r  r  Z3_mk_bvmul_no_underflowr   r   rP   r(  s     r   BVMulNoUnderflowr    rq  r   c                   *    \ rS rSrSrS rS rS rSrg)r  i   zArray sorts.c                 r    [        [        U R                  5       U R                  5      U R                  5      $ )ziReturn the domain of the array sort `self`.

>>> A = ArraySort(IntSort(), BoolSort())
>>> A.domain()
Int
)rE  Z3_get_array_sort_domainr   r   rP   r   s    r   r  ArraySortRef.domain#  s*     4T\\^TXXNPTPXPXYYr   c                 t    [        [        U R                  5       U R                  U5      U R                  5      $ )z4Return the domain of the array sort `self`.
        )rE  Z3_get_array_sort_domain_nr   r   rP   r  s     r   domain_nArraySortRef.domain_n,  s-     6t||~txxQRSUYU]U]^^r   c                 r    [        [        U R                  5       U R                  5      U R                  5      $ )zhReturn the range of the array sort `self`.

>>> A = ArraySort(IntSort(), BoolSort())
>>> A.range()
Bool
)rE  Z3_get_array_sort_ranger   r   rP   r   s    r   r7  ArraySortRef.range1  s'     3DLLNDHHMtxxXXr   r   N)	r   r   r   r   r   r  r  r7  r   r   r   r   r  r     s    Z_
Yr   r  c                   <    \ rS rSrSrS rS rS rS rS r	S r
S	rg
)r=  i;  zArray expressions. c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ )zReturn the array sort of the array expression `self`.

>>> a = Array('a', IntSort(), BoolSort())
>>> a.sort()
Array(Int, Bool)
)r  r  r   r   rP   r   s    r   r]  ArrayRef.sort>  s(     KFQQr   c                 >    U R                  5       R                  5       $ )zdShorthand for `self.sort().domain()`.

>>> a = Array('a', IntSort(), BoolSort())
>>> a.domain()
Int
)r]  r  r   s    r   r  ArrayRef.domainG  s     yy{!!##r   c                 @    U R                  5       R                  U5      $ )z'Shorthand for self.sort().domain_n(i)`.)r]  r  r  s     r   r  ArrayRef.domain_nP  s    yy{##A&&r   c                 >    U R                  5       R                  5       $ )zcShorthand for `self.sort().range()`.

>>> a = Array('a', IntSort(), BoolSort())
>>> a.range()
Bool
)r]  r7  r   s    r   r7  ArrayRef.rangeT  s     yy{  ""r   c                     [        X5      $ )zReturn the Z3 expression `self[arg]`.

>>> a = Array('a', IntSort(), BoolSort())
>>> i = Int('i')
>>> a[i]
a[i]
>>> a[i].sexpr()
'(select a i)'
)r%  r&  s     r   r'  ArrayRef.__getitem__]  s     T''r   c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ r   )rH  Z3_mk_array_defaultr   r   rP   r   s    r   defaultArrayRef.defaulti  *    /NPTPXPXYYr   r   N)r   r   r   r   r   r]  r  r  r7  r'  r  r   r   r   r   r=  r=  ;  s%    R$'#
(Zr   r=  c                 \   [        U[        5      (       a  [        [        U5      5       Vs/ s H2  o R	                  5       R                  U5      R                  X   5      PM4     nn[        U5      u  pE[        [        U R                  5       U R                  5       XT5      U R                  5      $ U R	                  5       R                  5       R                  U5      n[        [        U R                  5       U R                  5       UR                  5       5      U R                  5      $ s  snf r   )r   r\   r7  r[   r]  r  r_  r@  rH  Z3_mk_select_nr   r   rP   r  Z3_mk_select)arrc   r<  rb   r;  r:  s         r   r%  r%  m  s    #u<A#c(OLOq	""1%**362OL!$'	N2::<bPRTRXRXYY
'')



!
!#
&CRZZ\299;

MrvvVV	 Ms   9D)c                     [        U R                  R                  5       [        U R                  R                  5       U R                  5      5      [
        :H  $ r   )rJ  rP   rM   r  r   r  r%  s    r   is_array_sortr  v  s3    AEEIIKQUUYY[!%%)HI]ZZr   c                 "    [        U [        5      $ )zReturn `True` if `a` is a Z3 array expression.

>>> a = Array('a', IntSort(), IntSort())
>>> is_array(a)
True
>>> is_array(Store(a, 0, 1))
True
>>> is_array(a[0])
False
)r   r=  r%  s    r   is_arrayr  z  s     a""r   c                 "    [        U [        5      $ )zReturn `True` if `a` is a Z3 constant array.

>>> a = K(IntSort(), 10)
>>> is_const_array(a)
True
>>> a = Array('a', IntSort(), IntSort())
>>> is_const_array(a)
False
rk  Z3_OP_CONST_ARRAYr%  s    r   is_const_arrayr         Q)**r   c                 "    [        U [        5      $ )zReturn `True` if `a` is a Z3 constant array.

>>> a = K(IntSort(), 10)
>>> is_K(a)
True
>>> a = Array('a', IntSort(), IntSort())
>>> is_K(a)
False
r  r%  s    r   is_Kr    r  r   c                 "    [        U [        5      $ )zReturn `True` if `a` is a Z3 map array expression.

>>> f = Function('f', IntSort(), IntSort())
>>> b = Array('b', IntSort(), IntSort())
>>> a  = Map(f, b)
>>> a
Map(f, b)
>>> is_map(a)
True
>>> is_map(b)
False
)rk  Z3_OP_ARRAY_MAPr%  s    r   is_mapr    s     Q((r   c                 "    [        U [        5      $ )zpReturn `True` if `a` is a Z3 default array expression.
>>> d = Default(K(IntSort(), 10))
>>> is_default(d)
True
)rk  Z3_OP_ARRAY_DEFAULTr%  s    r   
is_defaultr    s     Q+,,r   c           
         [        5       (       a  [        [        U 5      S5        [        [	        U R                  5       [        U R                  5       U R                  5       R                  S5      5      U R                  S9$ )a  Return the function declaration associated with a Z3 map array expression.

>>> f = Function('f', IntSort(), IntSort())
>>> b = Array('b', IntSort(), IntSort())
>>> a  = Map(f, b)
>>> eq(f, get_map_func(a))
True
>>> get_map_func(a)
f
>>> get_map_func(a)(0)
f(0)
z!Z3 array map expression expected.r   r   )
r   r;   r  r  Z3_to_func_declr   r  r  r   rP   r%  s    r   get_map_funcr    s]     zz6!9ABIIK%aiik1668<<C	
 EE r   c                     [        U 5      n [        5       (       a  [        [        U 5      S:  S5        [        U 5      S-
  nX   nU S   n[        5       (       aA  U  H;  n[        [	        U5      S5        [        UR
                  UR
                  :H  S5        M=     UR
                  n[        U 5      S:X  a9  [        [        UR                  5       UR                  UR                  5      U5      $ [        U-  " 5       n[        U5       H  nX   R                  Xg'   M     [        [        UR                  5       XUR                  5      U5      $ )zReturn the Z3 array sort with the given domain and range sorts.

>>> A = ArraySort(IntSort(), BoolSort())
>>> A
Array(Int, Bool)
>>> A.domain()
Int
>>> A.range()
Bool
>>> AA = ArraySort(IntSort(), A)
>>> AA
Array(Int, Array(Int, Bool))
r   r  r   r  r/  rx   )rd   r   r;   r[   ru  rP   r  Z3_mk_array_sortrM   r   rx  r7  Z3_mk_array_sort_n)r  r  r   drH   rP   r  r<  s           r   rl  rl    s     C.Czz3s8a<!BCHqLE
AAAzzAwqz#56quu~'9:  %%C
3x1},SWWYquuEsKK%<
C5\ *3779e!%%H#NNr   c           	          [        U5      nUR                  n[        [        UR	                  5       [        X5      UR                  5      U5      $ )zReturn an array constant named `name` with the given domain and range sorts.

>>> a = Array('a', IntSort(), IntSort())
>>> a.sort()
Array(Int, Int)
>>> a[0]
a[0]
)rl  rP   r=  ry  rM   rQ   r   )r?   sortsrH   rP   s       r   Arrayr    s<     	%A
%%CK	9T+?GMMr   c           
         [        5       (       a  [        [        U 5      S5        [        U5      nU R                  n[        U5      S::  a  [        S5      e[        U5      S:X  a  US   nUS   nU R                  5       R                  5       R                  U5      nU R                  5       R                  5       R                  U5      n[        [        UR                  5       U R                  5       UR                  5       UR                  5       5      U5      $ U R                  5       R                  5       R                  US   5      n[        [        U5      S-
  5       Vs/ s H2  o0R                  5       R                  U5      R                  X   5      PM4     nn[!        U5      u  pg[        [#        UR                  5       U R                  5       XvUR                  5       5      U5      $ s  snf )a   Return a Z3 store array expression.

>>> a    = Array('a', IntSort(), IntSort())
>>> i, v = Ints('i v')
>>> s    = Update(a, i, v)
>>> s.sort()
Array(Int, Int)
>>> prove(s[i] == v)
proved
>>> j    = Int('j')
>>> prove(Implies(i != j, s[j] == a[j]))
proved
,First argument must be a Z3 array expressionr   z/array update requires index and value argumentsrx   r   )r   r;   r  rd   rP   r[   r9   r]  r  r_  r7  rH  Z3_mk_storerM   r   r  r@  Z3_mk_store_n)r   rb   rP   r<  r   idxsr;  r:  s           r   Updater    si    zz=#%STT?D
%%C
4yA~KLL
4yA~GGFFHOO""1%FFHNN!!!$K	188:qxxz188:VX[\\	d2h'A8=c$ik8JK8J1FFHa %%dg.8JDKd#IEcggiR
SUXYY Ls   "9G,c                 j    [        5       (       a  [        [        U 5      S5        U R                  5       $ )zgReturn a default value for array expression.
>>> b = K(IntSort(), 1)
>>> prove(Default(b) == 1)
proved
r  )r   r;   r  r  r%  s    r   Defaultr  "  s'     zz=#%ST99;r   c                     [        X5      $ )zReturn a Z3 store array expression.

>>> a    = Array('a', IntSort(), IntSort())
>>> i, v = Ints('i v')
>>> s    = Store(a, i, v)
>>> s.sort()
Array(Int, Int)
>>> prove(s[i] == v)
proved
>>> j    = Int('j')
>>> prove(Implies(i != j, s[j] == a[j]))
proved
)r  r   rb   s     r   Storer  -  s     !?r   c                 h    [        U5      n[        5       (       a  [        [        U 5      S5        X   $ )zReturn a Z3 select array expression.

>>> a = Array('a', IntSort(), IntSort())
>>> i = Int('i')
>>> Select(a, i)
a[i]
>>> eq(Select(a, i), a[i])
True
r  )rd   r   r;   r  r  s     r   Selectr  >  s+     T?Dzz=#%ST7Nr   c           
         [        U5      n[        5       (       a  [        [        U5      S:  S5        [        [	        U 5      S5        [        [        U Vs/ s H  n[        U5      PM     sn5      S5        [        [        U5      U R                  5       :H  S5        [        U5      u  p4U R                  n[        [        UR                  5       U R                  XC5      U5      $ s  snf )a  Return a Z3 map array expression.

>>> f = Function('f', IntSort(), IntSort(), IntSort())
>>> a1 = Array('a1', IntSort(), IntSort())
>>> a2 = Array('a2', IntSort(), IntSort())
>>> b  = Map(f, a1, a2)
>>> b
Map(f, a1, a2)
>>> prove(b[0] == f(a1[0], a2[0]))
proved
r   z)At least one Z3 array expression expectedz0First argument must be a Z3 function declarationzZ3 array expected expectedzNumber of arguments mismatch)rd   r   r;   r[   r  r
  r  r  r@  rP   r=  	Z3_mk_maprM   r   )r  rb   r   r;  r:  rP   s         r   Mapr  N  s     T?Dzz3t9q="MN<?$VW3T2TT235QR3t9	)+IJd#IE
%%CIcggi:C@@	 3s   C%c                    [        5       (       a  [        [        U 5      S5        U R                  n[	        U5      (       d  [        X5      n[        [        UR                  5       U R                  UR                  5       5      U5      $ )zReturn a Z3 constant array expression.

>>> a = K(IntSort(), 10)
>>> a
K(Int, 10)
>>> a.sort()
Array(Int, Int)
>>> i = Int('i')
>>> a[i]
K(Int, 10)[i]
>>> simplify(a[i])
10
r  )r   r;   ru  rP   r\  rP  r=  Z3_mk_const_arrayrM   r   r   )r  r   rP   s      r   Kr  e  s]     zz73<!34
''C1::Q%cggi!((*EsKKr   c                 6   U R                   n[        5       (       a>  [        [        U 5      =(       a"    [	        U5      =(       d    UR                  5       S5        [        [        UR                  5       U R                  5       UR                  5       5      U5      $ )z{Return extensionality index for one-dimensional arrays.
>> a, b = Consts('a b', SetSort(IntSort()))
>> Ext(a, b)
Ext(a, b)
zarguments must be arrays)
rP   r   r;   r  r  r  rH  Z3_mk_array_extrM   r   rj  s      r   Extr  {  s`     %%Czz=#F!)EHbc	188:qxxzJCPPr   c                     U R                   n[        X5      n[        [        UR	                  5       U R                  5       UR                  5       5      U5      $ r   )rP   rP  rH  Z3_mk_set_has_sizerM   r   )r   r   rP   s      r   
SetHasSizer    s>    
%%CA*3779ahhj!((*MsSSr   c                 "    [        U [        5      $ )zReturn `True` if `a` is a Z3 array select application.

>>> a = Array('a', IntSort(), IntSort())
>>> is_select(a)
False
>>> i = Int('i')
>>> is_select(a[i])
True
)rk  Z3_OP_SELECTr%  s    r   	is_selectr    s     Q%%r   c                 "    [        U [        5      $ )zReturn `True` if `a` is a Z3 array store application.

>>> a = Array('a', IntSort(), IntSort())
>>> is_store(a)
False
>>> is_store(Store(a, 0, 1))
True
)rk  Z3_OP_STOREr%  s    r   is_storer    s     Q$$r   c                 *    [        U [        5       5      $ )z%Create a set sort over element sort s)rl  r'  rG   s    r   SetSortr    s    Q
##r   c                 v    U R                   n[        [        UR                  5       U R                  5      U5      $ )z;Create the empty set
>>> EmptySet(IntSort())
K(Int, False)
)rP   r=  Z3_mk_empty_setrM   r   rO   s     r   EmptySetr    s+    
 %%COCGGIquu5s;;r   c                 v    U R                   n[        [        UR                  5       U R                  5      U5      $ )z8Create the full set
>>> FullSet(IntSort())
K(Int, True)
)rP   r=  Z3_mk_full_setrM   r   rO   s     r   FullSetr    s+    
 %%CN3779aee4c::r   c                      [        U 5      n [        U 5      n[        U 5      u  p#[        [	        UR                  5       X25      U5      $ )zTake the union of sets
>>> a = Const('a', SetSort(IntSort()))
>>> b = Const('b', SetSort(IntSort()))
>>> SetUnion(a, b)
union(a, b)
)rd   r2  r@  r=  Z3_mk_set_unionrM   rt  s       r   SetUnionr    s=     T?D
 
&Cd#IEOCGGIr93??r   c                      [        U 5      n [        U 5      n[        U 5      u  p#[        [	        UR                  5       X25      U5      $ )zTake the union of sets
>>> a = Const('a', SetSort(IntSort()))
>>> b = Const('b', SetSort(IntSort()))
>>> SetIntersect(a, b)
intersection(a, b)
)rd   r2  r@  r=  Z3_mk_set_intersectrM   rt  s       r   SetIntersectr    s>     T?D
 
&Cd#IE'	2=sCCr   c                     [        X/5      n[        X5      n[        [        UR	                  5       U R                  5       UR                  5       5      U5      $ )zaAdd element e to set s
>>> a = Const('a', SetSort(IntSort()))
>>> SetAdd(a, 1)
Store(a, 1, True)
)r2  rP  r=  Z3_mk_set_addrM   r   rH   rr   rP   s      r   SetAddr    B     !!
(CAM#'')QXXZDcJJr   c                     [        X/5      n[        X5      n[        [        UR	                  5       U R                  5       UR                  5       5      U5      $ )zeRemove element e to set s
>>> a = Const('a', SetSort(IntSort()))
>>> SetDel(a, 1)
Store(a, 1, False)
)r2  rP  r=  Z3_mk_set_delrM   r   r  s      r   SetDelr    r  r   c                 ~    U R                   n[        [        UR                  5       U R	                  5       5      U5      $ )zbThe complement of set s
>>> a = Const('a', SetSort(IntSort()))
>>> SetComplement(a)
complement(a)
)rP   r=  Z3_mk_set_complementrM   r   rO   s     r   SetComplementr    s.     %%C(AHHJ?EEr   c                     [        X/5      n[        [        UR                  5       U R	                  5       UR	                  5       5      U5      $ )zThe set difference of a and b
>>> a = Const('a', SetSort(IntSort()))
>>> b = Const('b', SetSort(IntSort()))
>>> SetDifference(a, b)
setminus(a, b)
)r2  r=  Z3_mk_set_differencerM   r   rj  s      r   SetDifferencer    s9     !!
(C(AHHJ
KSQQr   c                     [        X/5      n[        X5      n [        [        UR	                  5       U R                  5       UR                  5       5      U5      $ )z_Check if e is a member of set s
>>> a = Const('a', SetSort(IntSort()))
>>> IsMember(1, a)
a[1]
)r2  rP  r  Z3_mk_set_memberrM   r   )rr   rH   rP   s      r   IsMemberr    sC     !!
(CA#CGGIqxxz188:FLLr   c                     [        X/5      n[        [        UR                  5       U R	                  5       UR	                  5       5      U5      $ )zCheck if a is a subset of b
>>> a = Const('a', SetSort(IntSort()))
>>> b = Const('b', SetSort(IntSort()))
>>> IsSubset(a, b)
subset(a, b)
)r2  r  Z3_mk_set_subsetrM   r   rj  s      r   IsSubsetr    s9     !!
(C#CGGIqxxz188:FLLr   c                     [        U [        5      (       d  g[        U 5      S:w  a  g[        U S   [        5      =(       a(    [        U S   [        5      =(       d    [        U S   5      $ )zEReturn `True` if acc is pair of the form (String, Datatype or Sort). Frx   r   r   )r   r\   r[   rl   Datatyperu  )accs    r   _valid_accessorr  $  sQ    c5!!
3x1}c!fc"X
3q68(D(WPSTUPVXr   c                   F    \ rS rSrSrSS jr0 4S jrS rS rS r	S	 r
S
rg)r  i-  a  Helper class for declaring Z3 datatypes.

>>> List = Datatype('List')
>>> List.declare('cons', ('car', IntSort()), ('cdr', List))
>>> List.declare('nil')
>>> List = List.create()
>>> # List is now a Z3 declaration
>>> List.nil
nil
>>> List.cons(10, List.nil)
cons(10, nil)
>>> List.cons(10, List.nil).sort()
List
>>> cons = List.cons
>>> nil  = List.nil
>>> car  = List.car
>>> cdr  = List.cdr
>>> n = cons(1, cons(0, nil))
>>> n
cons(1, cons(0, nil))
>>> simplify(cdr(n))
cons(0, nil)
>>> simplify(car(n))
1
Nc                 >    [        U5      U l        Xl        / U l        g r   )rL   rP   r?   constructors)r   r?   rP   s      r   r   Datatype.__init__H  s    C=	r   c                     [        U R                  U R                  5      n[        R                  " U R
                  5      Ul        U$ r   )r  r?   rP   copydeepcopyr  )r   r   r   s      r   r   Datatype.__deepcopy__M  s1    TYY)t'8'89r   c           
      ,   [        5       (       ac  [        [        U[        5      S5        [        [        U[        5      S5        [        [	        U Vs/ s H  n[        U5      PM     sn5      S5        U R                  R                  XU45        g s  snf )NString expectedz[Valid list of accessors expected. An accessor is a pair of the form (String, Datatype|Sort))r   r;   r   rl   r
  r  r  r  )r   r?   rec_namerb   r   s        r   declare_coreDatatype.declare_coreR  st    ::z$,.?@z(C02CD6A_Q'67m 	  $$!78 7s   Bc                     [        5       (       a)  [        [        U[        5      S5        [        US:g  S5        U R                  " USU-   /UQ76 $ )a  Declare constructor named `name` with the given accessors `args`.
Each accessor is a pair `(name, sort)`, where `name` is a string and `sort` a Z3 sort
or a reference to the datatypes being declared.

In the following example `List.declare('cons', ('car', IntSort()), ('cdr', List))`
declares the constructor named `cons` that builds a new List using an integer and a List.
It also declares the accessors `car` and `cdr`. The accessor `car` extracts the integer
of a `cons` cell, and `cdr` the list of a `cons` cell. After all constructors were declared,
we use the method create() to create the actual datatype in Z3.

>>> List = Datatype('List')
>>> List.declare('cons', ('car', IntSort()), ('cdr', List))
>>> List.declare('nil')
>>> List = List.create()
r  rY  z Constructor name cannot be emptyzis-)r   r;   r   rl   r  )r   r?   rb   s      r   declareDatatype.declare\  sH      ::z$,.?@trz#EF  ut|;d;;r   c                 @    SU R                   < SU R                  < S3$ )Nz	Datatype(, ))r?   r  r   s    r   r   Datatype.__repr__q  s    %)YY0A0ABBr   c                      [        U /5      S   $ )ar  Create a Z3 datatype based on the constructors declared using the method `declare()`.

The function `CreateDatatypes()` must be used to define mutually recursive datatypes.

>>> List = Datatype('List')
>>> List.declare('cons', ('car', IntSort()), ('cdr', List))
>>> List.declare('nil')
>>> List = List.create()
>>> List.nil
nil
>>> List.cons(10, List.nil)
cons(10, nil)
r   )CreateDatatypesr   s    r   createDatatype.createt  s     v&q))r   )r  rP   r?   r   )r   r   r   r   r   r   r   r  r  r   r  r   r   r   r   r  r  -  s+    4
 !# 
9<*C*r   r  c                   $    \ rS rSrSrS rS rSrg)ScopedConstructori  -Auxiliary object used to create Z3 datatypes.c                     Xl         X l        g r   rq   rP   r   rq   rP   s      r   r   ScopedConstructor.__init__      r   c                     U R                   R                  5       b7  [        b/  [        U R                   R                  5       U R                  5        g g g r   )rP   rM   Z3_del_constructorrq   r   s    r   r   ScopedConstructor.__del__  s9    88<<>%*<*Htxx||~tvv6 +I%r   r   Nr   r   r   r   r   r   r   r   r   r   r   r  r    s    77r   r  c                   $    \ rS rSrSrS rS rSrg)ScopedConstructorListi  r  c                     Xl         X l        g r   r   r!  s      r   r   ScopedConstructorList.__init__  r#  r   c                     U R                   R                  5       b7  [        b/  [        U R                   R                  5       U R                  5        g g g r   )rP   rM   Z3_del_constructor_listrq   r   s    r   r   ScopedConstructorList.__del__  s9    88<<>%*A*M#DHHLLNDFF; +N%r   r   Nr'  r   r   r   r)  r)    s    7<r   r)  c                     [        U 5      n [        5       (       a  [        [        U 5      S:  S5        [        [	        U  Vs/ s H  n[        U[        5      PM     sn5      S5        [        [	        U  Vs/ s H  oR                  U S   R                  :H  PM      sn5      S5        [        [	        U  Vs/ s H  oR                  / :g  PM     sn5      S5        U S   R                  n[        U 5      n[        U-  " 5       n[        U-  " 5       n[        U-  " 5       n/ n[        U5       GH  nX   n[        UR                  U5      XH'   [        UR                  5      n	[        U	-  " 5       n
[        U	5       GHx  nUR                  U   n[        US   U5      n[        US   U5      nUS   n[        U5      n[        U-  " 5       n[        U-  " 5       n[         R"                  U-  " 5       n[        U5       H  nUU   S   nUU   S   n[        UU5      UU'   [        U[        5      (       aH  [        5       (       a  [        U R%                  U5      S:H  S5        S	UU'   U R'                  U5      UU'   M  [        5       (       a  [        [)        U5      S
5        UR*                  UU'   SUU'   M     [-        UR/                  5       XUUUU5      X'   UR1                  [3        X   U5      5        GM{     [5        UR/                  5       X5      Xh'   UR1                  [7        Xh   U5      5        GM     [9        UR/                  5       X4XV5        / n[        U5       H  n[;        XX   U5      nUR=                  5       n	[        U	5       H  nUR?                  U5      nUR                  5       nURA                  5       nURA                  5       S:X  a  U" 5       n[C        UUU5        URE                  U5      n[C        USU-   U5        [        U5       H0  nURG                  UU5      n[C        UUR                  5       U5        M2     M     UR1                  U5        GM      [I        U5      $ s  snf s  snf s  snf )a  Create mutually recursive Z3 datatypes using 1 or more Datatype helper objects.

In the following example we define a Tree-List using two mutually recursive datatypes.

>>> TreeList = Datatype('TreeList')
>>> Tree     = Datatype('Tree')
>>> # Tree has two constructors: leaf and node
>>> Tree.declare('leaf', ('val', IntSort()))
>>> # a node contains a list of trees
>>> Tree.declare('node', ('children', TreeList))
>>> TreeList.declare('nil')
>>> TreeList.declare('cons', ('car', Tree), ('cdr', TreeList))
>>> Tree, TreeList = CreateDatatypes(Tree, TreeList)
>>> Tree.val(Tree.leaf(10))
val(leaf(10))
>>> simplify(Tree.val(Tree.leaf(10)))
10
>>> n1 = Tree.node(TreeList.cons(Tree.leaf(10), TreeList.cons(Tree.leaf(20), TreeList.nil)))
>>> n1
node(cons(leaf(10), cons(leaf(20), nil)))
>>> n2 = Tree.node(TreeList.cons(n1, TreeList.nil))
>>> simplify(n2 == n1)
False
>>> simplify(TreeList.car(Tree.children(n2)) == n1)
True
r   z'At least one Datatype must be specifiedzArguments must be Datatypesr/  zNon-empty Datatypes expectedr   rx   z8One and only one occurrence of each datatype is expectedNr  is_)%rd   r   r;   r[   r
  r   r  rP   r  Symbolrx  ConstructorListr7  rQ   r?   Constructorr'   r(   countrX  ru  r   Z3_mk_constructorrM   r  r  Z3_mk_constructor_listr)  Z3_mk_datatypesr  num_constructorsconstructorr  setattr
recognizeraccessorr\   )dsr  rP   r  r~  outclists	to_deleter<  num_cscsjrq   cnamernamefsnum_fsfnamesr  refsr   rC   ftyper  drefcref	cref_name
cref_arityrrefarefs                                 r   r  r    s   6 
2Bzz3r7Q; IJ3<A
1h/<=?\]3B7BqA*B78:LM3b9b",b9:<Z[
Q%))C
b'Cc\E#:.C#&FI3ZEQVVS)Q^^$F"%vAq!AadC(EadC(E1BWFvo(FF]%EMMF*-D6]1a1a%eS1q	eX..zz"HHUOq0V  $E!H hhuoDGzz"75>3EF$yyE!HDG! #" &cggivvuVZ[BE.ruc:;7 8 +3779fA	.vy#>?E F CGGIs37F3Zsvs+&&(vA##A&D		IJzz|q vD)T*??1%DD%)+T2:&}}Q*diik40 '  	d   = =79s   Q'5%Q,4Q1c                   0    \ rS rSrSrS rS rS rS rSr	g)	r  i  zDatatype sorts.c                 \    [        [        U R                  5       U R                  5      5      $ )a  Return the number of constructors in the given Z3 datatype.

>>> List = Datatype('List')
>>> List.declare('cons', ('car', IntSort()), ('cdr', List))
>>> List.declare('nil')
>>> List = List.create()
>>> # List is now a Z3 declaration
>>> List.num_constructors()
2
)r   %Z3_get_datatype_sort_num_constructorsr   r   r   s    r   r8   DatatypeSortRef.num_constructors   s!     8RSSr   c                     [        5       (       a  [        XR                  5       :  S5        [        [	        U R                  5       U R                  U5      U R                  5      $ )a1  Return a constructor of the datatype `self`.

>>> List = Datatype('List')
>>> List.declare('cons', ('car', IntSort()), ('cdr', List))
>>> List.declare('nil')
>>> List = List.create()
>>> # List is now a Z3 declaration
>>> List.num_constructors()
2
>>> List.constructor(0)
cons
>>> List.constructor(1)
nil
Invalid constructor index)r   r;   r8  r   Z3_get_datatype_sort_constructorr   r   rP   r  s     r   r9  DatatypeSortRef.constructor  sK     ::s22446QR;DLLNDHHVYZ\`\d\deer   c                     [        5       (       a  [        XR                  5       :  S5        [        [	        U R                  5       U R                  U5      U R                  5      $ )aC  In Z3, each constructor has an associated recognizer predicate.

If the constructor is named `name`, then the recognizer `is_name`.

>>> List = Datatype('List')
>>> List.declare('cons', ('car', IntSort()), ('cdr', List))
>>> List.declare('nil')
>>> List = List.create()
>>> # List is now a Z3 declaration
>>> List.num_constructors()
2
>>> List.recognizer(0)
is(cons)
>>> List.recognizer(1)
is(nil)
>>> simplify(List.is_nil(List.cons(10, List.nil)))
False
>>> simplify(List.is_cons(List.cons(10, List.nil)))
True
>>> l = Const('l', List)
>>> simplify(List.is_cons(l))
is(cons, l)
zInvalid recognizer index)r   r;   r8  r  Z3_get_datatype_sort_recognizerr   r   rP   r  s     r   r;  DatatypeSortRef.recognizer   sK    0 ::s22446PQ:4<<>488UXY[_[c[cddr   c                    [        5       (       aG  [        XR                  5       :  S5        [        X R                  U5      R	                  5       :  S5        [        [        U R                  5       U R                  X5      U R                  S9$ )a  In Z3, each constructor has 0 or more accessor.
The number of accessors is equal to the arity of the constructor.

>>> List = Datatype('List')
>>> List.declare('cons', ('car', IntSort()), ('cdr', List))
>>> List.declare('nil')
>>> List = List.create()
>>> List.num_constructors()
2
>>> List.constructor(0)
cons
>>> num_accs = List.constructor(0).arity()
>>> num_accs
2
>>> List.accessor(0, 0)
car
>>> List.accessor(0, 1)
cdr
>>> List.constructor(1)
nil
>>> num_accs = List.constructor(1).arity()
>>> num_accs
0
rV  zInvalid accessor indexr   )
r   r;   r8  r9  r  r  )Z3_get_datatype_sort_constructor_accessorr   r   rP   )r   r<  rC  s      r   r<  DatatypeSortRef.accessor<  so    2 ::q00224OPq++A.44668PQ5dllndhhPQU
 	
r   r   N)
r   r   r   r   r   r8  r9  r;  r<  r   r   r   r   r  r    s    Tf&e8
r   r  c                       \ rS rSrSrS rSrg)r>  i^  zDatatype expressions.c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ )z;Return the datatype sort of the datatype expression `self`.)r  r  r   r   rP   r   s    r   r]  DatatypeRef.sorta  s&    {4<<>4;;=I488TTr   r   N)r   r   r   r   r   r]  r   r   r   r   r>  r>  ^  s    Ur   r>  c           	      r    [        U5      n[        [        UR                  5       [	        X5      5      U5      $ )z\Create a reference to a sort that was declared, or will be declared, as a recursive datatype)rL   r  Z3_mk_datatype_sortrM   rQ   r  s     r   DatatypeSortrd  e  s,    
3-C.swwy)D:NOQTUUr   c           	      R   [        X5      n[        [        U5      5       Vs/ s H  nSU-  X   4PM     nnUR                  " U /UQ76   UR	                  5       nX3R                  S5      [        [        U5      5       Vs/ s H  oCR                  SU5      PM     sn4$ s  snf s  snf )zCreate a named tuple sort base on a set of underlying sorts
Example:
    >>> pair, mk_pair, (first, second) = TupleSort("pair", [IntSort(), StringSort()])
	project%dr   r  r7  r[   r  r  r9  r<  )r?   r  rP   r\   r<  projectss         r   	TupleSortri  j  s    
 TE5:3u:5FG5Fq%(+5FHG	MM$""LLNE##A&uSQVZGX(YGX!1)=GX(YYY H )Zs   B B$c           	      >   [        X5      n[        [        U5      5       H  nUR                  SU-  SU-  X   45        M!     UR	                  5       nU[        [        U5      5       Vs/ s H%  oCR                  U5      UR                  US5      4PM'     sn4$ s  snf )zCreate a named tagged union sort base on a set of underlying sorts
Example:
    >>> sum, ((inject0, extract0), (inject1, extract1)) = DisjointSum("+", [IntSort(), StringSort()])
zinject%drf  r   rg  )r?   r  rP   sumr<  s        r   DisjointSumrl  v  s    
 4
C3u:JN[1_eh$?@ 
**,C5UCTUCTa//!$cll1a&89CTUUUUs   *,Bc                    [        5       (       af  [        [        U [        5      S5        [        [	        U Vs/ s H  n[        U[        5      PM     sn5      S5        [        [        U5      S:  S5        [        U5      n[        U5      n[        U-  " 5       n[        U5       H  n[        X   U5      XV'   M     [        U-  " 5       n[        U-  " 5       n[        X5      n [        [        UR                  5       XXWU5      U5      n	/ n
[        U5       H   nU
R                  [        Xv   U5      5        M"     U
 Vs/ s H	  o" 5       PM     n
nX4$ s  snf s  snf )zReturn a new enumeration sort named `name` containing the given values.

The result is a pair (sort, list of constants).
Example:
    >>> Color, (red, green, blue) = EnumSort('Color', ['red', 'green', 'blue'])
zName must be a stringz'Enumeration sort values must be stringsr   zAt least one value expected)r   r;   r   rl   r
  r[   rL   r1  r7  rQ   r6  r  Z3_mk_enumeration_sortrM   r  r  )r?   valuesrP   r   r  
_val_namesr<  _values_testersSVr   s               r   EnumSortru    s#    zz:dC(*AB3F;Fq
1c*F;<>gh3v;?$AB
3-C
f+C3,!J3Z!&)S1
 #~ G3!HTD.swwy$ZZbcehiA
A3Z	WZ-. aaA4K < 	s   E>Ec                   F    \ rS rSrSrSS jr0 4S jrS rS rS r	S	 r
S
rg)	ParamsRefi  zSet of parameters used to configure Solvers, Tactics and Simplifiers in Z3.

Consider using the function `args2params` to create instances of this object.
Nc                     [        U5      U l        Uc)  [        U R                  R                  5       5      U l        OX l        [        U R                  R                  5       U R                  5        g r   )rL   rP   Z3_mk_paramsrM   r  Z3_params_inc_ref)r   rP   r  s      r   r   ParamsRef.__init__  sE    C=>&txx||~6DK K$((,,.$++6r   c                 B    [        U R                  U R                  5      $ r   )rw  rP   r  r   s     r   r   ParamsRef.__deepcopy__  s    4;;//r   c                     U R                   R                  5       b7  [        b/  [        U R                   R                  5       U R                  5        g g g r   )rP   rM   Z3_params_dec_refr  r   s    r   r   ParamsRef.__del__  s9    88<<>%*;*Gdhhllndkk: +H%r   c           	         [        5       (       a  [        [        U[        5      S5        [	        XR
                  5      n[        U[        5      (       a0  [        U R
                  R                  5       U R                  X25        g[        U5      (       a0  [        U R
                  R                  5       U R                  X25        g[        U[        5      (       a0  [        U R
                  R                  5       U R                  X25        g[        U[        5      (       aD  [        U R
                  R                  5       U R                  U[	        X R
                  5      5        g[        5       (       a  [        SS5        gg)z"Set parameter name with value val.zparameter name must be a stringFzinvalid parameter valueN)r   r;   r   rl   rQ   rP   rk   Z3_params_set_boolrM   r  r   Z3_params_set_uintrR  Z3_params_set_doubleZ3_params_set_symbol)r   r?   rn   name_syms       r   r^   ParamsRef.set  s    ::z$,.OPT88,c4  txx||~t{{HJS\\txx||~t{{HJU## hLS!! h	RUW_W_H`azz5";< r   c                 ^    [        U R                  R                  5       U R                  5      $ r   )Z3_params_to_stringrP   rM   r  r   s    r   r   ParamsRef.__repr__  s    "488<<>4;;??r   c                     [        [        U[        5      S5        [        U R                  R                  5       U R                  UR                  5        g )Nz"parameter description set expected)r;   r   r   Z3_params_validaterP   rM   r  descr)r   r=  s     r   validateParamsRef.validate  s2    :b.13WX488<<>4;;Ar   )rP   r  NN)r   r   r   r   r   r   r   r   r^   r   r  r   r   r   r   rw  rw    s,    
7 !# 0;="@Br   rw  c                     [        5       (       a  [        [        U 5      S-  S:H  S5        Sn[        U5      nU  H  nUc  UnM
  UR	                  X55        SnM     U H  nX   nUR	                  Xg5        M     U$ )zConvert python arguments into a Z3_params object.
A ':' is added to the keywords, and '_' is replaced with '-'

>>> args2params(['model', True, 'relevancy', 2], {'elim_and' : True})
(params model true relevancy 2 elim_and true)
rx   r   ry   N)r   r;   r[   rw  r^   )	argumentskeywordsrP   r   r   r   r   r   s           r   args2paramsr    s{     zz3y>A%*,abD#A<DEE$ND  K	a  Hr   c                   ^    \ rS rSrSrSS jr0 4S jrS rS rS r	S	 r
S
 rS rS rS rSrg)r   i  zNSet of parameter descriptions for Solvers, Tactics and Simplifiers in Z3.
    Nc                     [        [        U[        5      S5        [        U5      U l        Xl        [        U R                  R                  5       U R
                  5        g )Nz%parameter description object expected)r;   r   ParamDescrsrL   rP   r  Z3_param_descrs_inc_refrM   )r   r  rP   s      r   r   ParamDescrsRef.__init__  s<    :e[13Z[C=


;r   c                 B    [        U R                  U R                  5      $ r   )ParamsDescrsRefr  rP   r   s     r   r   ParamDescrsRef.__deepcopy__  s    tzz48844r   c                     U R                   R                  5       b7  [        b/  [        U R                   R                  5       U R                  5        g g g r   )rP   rM   Z3_param_descrs_dec_refr  r   s    r   r   ParamDescrsRef.__del__  s9    88<<>%*A*M#DHHLLNDJJ? +N%r   c                 p    [        [        U R                  R                  5       U R                  5      5      $ z@Return the size of in the parameter description `self`.
        )r   Z3_param_descrs_sizerP   rM   r  r   s    r   r  ParamDescrsRef.size  s%     '

CDDr   c                 "    U R                  5       $ r  r  r   s    r   __len__ParamDescrsRef.__len__  s     yy{r   c                     [        U R                  [        U R                  R                  5       U R                  U5      5      $ )zLReturn the i-th parameter name in the parameter description `self`.
        )rX   rP   Z3_param_descrs_get_namerM   r  r  s     r   get_nameParamDescrsRef.get_name  s.     $(($<TXX\\^TZZYZ$[\\r   c                     [        U R                  R                  5       U R                  [	        XR                  5      5      $ )z4Return the kind of the parameter named `n`.
        )Z3_param_descrs_get_kindrP   rM   r  rQ   r   r>   s     r   get_kindParamDescrsRef.get_kind  s,     (

IaQYQYDZ[[r   c                     [        U R                  R                  5       U R                  [	        XR                  5      5      $ )zDReturn the documentation string of the parameter named `n`.
        )!Z3_param_descrs_get_documentationrP   rM   r  rQ   r  s     r   get_documentation ParamDescrsRef.get_documentation  s-     1YWXZbZbMcddr   c                 f    [        U5      (       a  U R                  U5      $ U R                  U5      $ r   )r   r  r  r&  s     r   r'  ParamDescrsRef.__getitem__  s)    3<<==%%==%%r   c                 ^    [        U R                  R                  5       U R                  5      $ r   )Z3_param_descrs_to_stringrP   rM   r  r   s    r   r   ParamDescrsRef.__repr__  s    (DDr   )rP   r  r   )r   r   r   r   r   r   r   r   r  r  r  r  r  r'  r   r   r   r   r   r   r     sD    < !# 5@E

]
\
e
&Er   r   c                       \ rS rSrSrSS jrS rS rS rS r	S	 r
S
 rS rS rS rS rS rS rS rS rS rS rSS jrS rS r0 4S jrS rS rSrg)Goali"  a8  Goal is a collection of constraints we want to find a solution or show to be unsatisfiable (infeasible).

Goals are processed using Tactics. A Tactic transforms a goal into a set of subgoals.
A goal has a solution if one of its subgoals has a solution.
A goal is unsatisfiable if all subgoals are unsatisfiable.
Nc                 J   [        5       (       a  [        US L =(       d    US LS5        [        U5      U l        XPl        U R                  c*  [        U R                  R                  5       XU5      U l        [        U R                  R                  5       U R                  5        g )NzIIf goal is different from None, then ctx must be also different from None)r   r;   rL   rP   goal
Z3_mk_goalrM   Z3_goal_inc_ref)r   modelsunsat_coresproofsrP   r  s         r   r   Goal.__init__*  sp    ::tt|6s$bdC=	99"488<<>6ODI		2r   c                     U R                   bS  U R                  R                  5       b7  [        b/  [        U R                  R                  5       U R                   5        g g g g r   )r  rP   rM   Z3_goal_dec_refr   s    r   r   Goal.__del__4  sE    99 TXX\\^%?OD_DHHLLNDII6 E`%? r   c                 p    [        [        U R                  R                  5       U R                  5      5      $ )a  Return the depth of the goal `self`.
The depth corresponds to the number of tactics applied to `self`.

>>> x, y = Ints('x y')
>>> g = Goal()
>>> g.add(x == 0, y >= x + 1)
>>> g.depth()
0
>>> r = Then('simplify', 'solve-eqs')(g)
>>> # r has 1 subgoal
>>> len(r)
1
>>> r[0].depth()
2
)r   Z3_goal_depthrP   rM   r  r   s    r   depth
Goal.depth8  s$      =;<<r   c                 ^    [        U R                  R                  5       U R                  5      $ )a  Return `True` if `self` contains the `False` constraints.

>>> x, y = Ints('x y')
>>> g = Goal()
>>> g.inconsistent()
False
>>> g.add(x == 0, x == 1)
>>> g
[x == 0, x == 1]
>>> g.inconsistent()
False
>>> g2 = Tactic('propagate-values')(g)[0]
>>> g2.inconsistent()
True
)Z3_goal_inconsistentrP   rM   r  r   s    r   inconsistentGoal.inconsistentJ  s      $DHHLLNDII>>r   c                 ^    [        U R                  R                  5       U R                  5      $ )a  Return the precision (under-approximation, over-approximation, or precise) of the goal `self`.

>>> g = Goal()
>>> g.prec() == Z3_GOAL_PRECISE
True
>>> x, y = Ints('x y')
>>> g.add(x == y + 1)
>>> g.prec() == Z3_GOAL_PRECISE
True
>>> t  = With(Tactic('add-bounds'), add_bound_lower=0, add_bound_upper=10)
>>> g2 = t(g)[0]
>>> g2
[x == y + 1, x <= 10, x >= 0, y <= 10, y >= 0]
>>> g2.prec() == Z3_GOAL_PRECISE
False
>>> g2.prec() == Z3_GOAL_UNDER
True
)Z3_goal_precisionrP   rM   r  r   s    r   r=  	Goal.prec\  s    & !;;r   c                 "    U R                  5       $ )zNAlias for `prec()`.

>>> g = Goal()
>>> g.precision() == Z3_GOAL_PRECISE
True
)r=  r   s    r   rM  Goal.precisionq  s     yy{r   c                 p    [        [        U R                  R                  5       U R                  5      5      $ )zReturn the number of constraints in the goal `self`.

>>> g = Goal()
>>> g.size()
0
>>> x, y = Ints('x y')
>>> g.add(x == 0, y > x)
>>> g.size()
2
)r   Z3_goal_sizerP   rM   r  r   s    r   r  	Goal.sizez  s$     <		:;;r   c                 "    U R                  5       $ )zReturn the number of constraints in the goal `self`.

>>> g = Goal()
>>> len(g)
0
>>> x, y = Ints('x y')
>>> g.add(x == 0, y > x)
>>> len(g)
2
r  r   s    r   r  Goal.__len__  s     yy{r   c                     [        [        U R                  R                  5       U R                  U5      U R                  5      $ )zReturn a constraint in the goal `self`.

>>> g = Goal()
>>> x, y = Ints('x y')
>>> g.add(x == 0, y > x)
>>> g.get(0)
x == 0
>>> g.get(1)
y > x
)rH  Z3_goal_formularP   rM   r  r  s     r   getGoal.get  s,     ODHHLLNDIIqI488TTr   c                 N    U[        U 5      :  a  [        eU R                  U5      $ )zReturn a constraint in the goal `self`.

>>> g = Goal()
>>> x, y = Ints('x y')
>>> g.add(x == 0, y > x)
>>> g[0]
x == 0
>>> g[1]
y > x
)r[   
IndexErrorr  r&  s     r   r'  Goal.__getitem__  s$     #d)xx}r   c                     [        U5      n[        U R                  5      nU HQ  nUR                  U5      n[	        U R                  R                  5       U R                  UR                  5       5        MS     g)zyAssert constraints into the goal.

>>> x = Int('x')
>>> g = Goal()
>>> g.assert_exprs(x > 0, x < 2)
>>> g
[x > 0, x < 2]
N)rd   r'  rP   r_  Z3_goal_assertrM   r  r   )r   rb   rH   rc   s       r   assert_exprsGoal.assert_exprs  sR     TXXC&&+C488<<>499cjjlC r   c                 "    U R                   " U6   g)zbAdd constraints.

>>> x = Int('x')
>>> g = Goal()
>>> g.append(x > 0, x < 2)
>>> g
[x > 0, x < 2]
Nr  r   rb   s     r   r  Goal.append       	4 r   c                 "    U R                   " U6   g)zbAdd constraints.

>>> x = Int('x')
>>> g = Goal()
>>> g.insert(x > 0, x < 2)
>>> g
[x > 0, x < 2]
Nr  r  s     r   insertGoal.insert  r  r   c                 "    U R                   " U6   g)z_Add constraints.

>>> x = Int('x')
>>> g = Goal()
>>> g.add(x > 0, x < 2)
>>> g
[x > 0, x < 2]
Nr  r  s     r   r(  Goal.add  r  r   c                     [        5       (       a  [        [        U[        5      S5        [        [	        U R
                  R                  5       U R                  UR                  5      U R
                  5      $ )a  Retrieve model from a satisfiable goal
>>> a, b = Ints('a b')
>>> g = Goal()
>>> g.add(Or(a == 0, a == 1), Or(b == 0, b == 1), a > b)
>>> t = Then(Tactic('split-clause'), Tactic('solve-eqs'))
>>> r = t(g)
>>> r[0]
[Or(b == 0, b == 1), Not(0 <= b)]
>>> r[1]
[Or(b == 0, b == 1), Not(1 <= b)]
>>> # Remark: the subgoal r[0] is unsatisfiable
>>> # Creating a solver for solving the second subgoal
>>> s = Solver()
>>> s.add(r[1])
>>> s.check()
sat
>>> s.model()
[b = 0]
>>> # Model s.model() does not assign a value to `a`
>>> # It is a model for subgoal `r[1]`, but not for goal `g`
>>> # The method convert_model creates a model for `g` from a model for `r[1]`.
>>> r[1].convert_model(s.model())
[b = 0, a = 1]
zZ3 Model expected)	r   r;   r   ModelRefZ3_goal_convert_modelrP   rM   r  model)r   r  s     r   convert_modelGoal.convert_model  sM    2 ::z%24GH-dhhllndiiUW[W_W_``r   c                     [        U 5      $ r   r   r   s    r   r   Goal.__repr__  r   r   c                 ^    [        U R                  R                  5       U R                  5      $ )zJReturn a textual representation of the s-expression representing the goal.)Z3_goal_to_stringrP   rM   r  r   s    r   r  
Goal.sexpr   s     ;;r   c                 `    [        U R                  R                  5       U R                  U5      $ )z=Return a textual representation of the goal in DIMACS format.)Z3_goal_to_dimacs_stringrP   rM   r  r   include_namess     r   dimacsGoal.dimacs  s    '		=QQr   c                     [        5       (       a  [        [        U[        5      S5        [	        [        U R                  R                  5       U R                  UR                  5       5      US9$ )zCopy goal `self` to context `target`.

>>> x = Int('x')
>>> g = Goal()
>>> g.add(x > 10)
>>> g
[x > 10]
>>> c2 = Context()
>>> g2 = g.translate(c2)
>>> g2
[x > 10]
>>> g.ctx == main_ctx()
True
>>> g2.ctx == c2
True
>>> g2.ctx == main_ctx()
False
ztarget must be a contextr  rP   )	r   r;   r   ru   r  Z3_goal_translaterP   rM   r  r  s     r   r  Goal.translate  sI    & ::z&'24NO*488<<>499fjjlSY_``r   c                 8    U R                  U R                  5      $ r   r  r   s    r   r  Goal.__copy__  r  r   c                 8    U R                  U R                  5      $ r   r  r   s     r   r   Goal.__deepcopy__"  r  r   c                 J    [        S5      nUR                  " U /UQ70 UD6S   $ )zReturn a new simplified goal.

This method is essentially invoking the simplify tactic.

>>> g = Goal()
>>> x = Int('x')
>>> g.add(x + 1 >= 2)
>>> g
[x + 1 >= 2]
>>> g2 = g.simplify()
>>> g2
[x >= 1]
>>> # g was not modified
>>> g
[x + 1 >= 2]
ri  r   )rn  apply)r   r  r  ts       r   ri  Goal.simplify%  s,    " :wwt4i484Q77r   c                    [        U 5      nUS:X  a  [        SU R                  5      $ US:X  a  U R                  S5      $ [	        [        [        U 5      5       Vs/ s H  o R                  U5      PM     snU R                  5      $ s  snf )zReturn goal `self` as a single Z3 expression.

>>> x = Int('x')
>>> g = Goal()
>>> g.as_expr()
True
>>> g.add(x > 1)
>>> g.as_expr()
x > 1
>>> g.add(x < 10)
>>> g.as_expr()
And(x > 1, x < 10)
r   Tr   )r[   r  rP   r  r  r7  r   r:  r<  s      r   as_exprGoal.as_expr9  sn     Y74**1W88A;U3t9-=>-=-=>II>s   B)rP   r  )TFFNNT)r   r   r   r   r   r   r   r  r  r=  rM  r  r  r  r'  r  r  r  r(  r  r   r  r  r  r  r   ri  r  r   r   r   r   r  r  "  s    37=$?$<*<UD	!	!	!a:#<Ra.( !# (8(Jr   r  c                   p    \ rS rSrSrSS jrS rS rS rS r	S	 r
S
 rS rS rS r0 4S jrS rS rSrg)r_   iV  zA collection (vector) of ASTs.Nc                    S U l         Uc9  [        U5      U l        [        U R                  R	                  5       5      U l         OXl         Uc   eX l        [        U R                  R	                  5       U R                   5        g r   )vectorrL   rP   Z3_mk_ast_vectorrM   Z3_ast_vector_inc_ref)r   r   rP   s      r   r   AstVector.__init__Y  s[    9}DH*488<<>:DKK?"?Hdhhllndkk:r   c                     U R                   bS  U R                  R                  5       b7  [        b/  [        U R                  R                  5       U R                   5        g g g g r   )r  rP   rM   Z3_ast_vector_dec_refr   s    r   r   AstVector.__del__d  sF    ;;"txx||~'AF[Fg!$((,,.$++> Gh'A"r   c                 p    [        [        U R                  R                  5       U R                  5      5      $ )zReturn the size of the vector `self`.

>>> A = AstVector()
>>> len(A)
0
>>> A.push(Int('x'))
>>> A.push(Int('x'))
>>> len(A)
2
)r   Z3_ast_vector_sizerP   rM   r  r   s    r   r  AstVector.__len__h  s%     %dhhllndkkBCCr   c           
      D   [        U[        5      (       at  US:  a  XR                  5       -  nXR                  5       :  a  [        e[	        [        U R                  R                  5       U R                  U5      U R                  5      $ [        U[        5      (       a  / n[        UR                  U R                  5       5      6  HU  nUR                  [	        [        U R                  R                  5       U R                  U5      U R                  5      5        MW     U$ g)z}Return the AST at position `i`.

>>> A = AstVector()
>>> A.push(Int('x') + 1)
>>> A.push(Int('y'))
>>> A[0]
x + 1
>>> A[1]
y
r   N)r   r   r  r  r   Z3_ast_vector_getrP   rM   r  slicer7  indicesr  )r   r<  r  iis       r   r'  AstVector.__getitem__u  s     a1u\\^#LLN"  0aPRVRZRZ[[5!!FQYYt||~67k%dhhllndkk2FHH  8
 M "r   c                     XR                  5       :  a  [        e[        U R                  R	                  5       U R
                  XR                  5       5        g)zUpdate AST at position `i`.

>>> A = AstVector()
>>> A.push(Int('x') + 1)
>>> A.push(Int('y'))
>>> A[0]
x + 1
>>> A[0] = Int('x')
>>> A[0]
x
N)r  r  Z3_ast_vector_setrP   rM   r  r   )r   r<  r   s      r   __setitem__AstVector.__setitem__  s6     $((,,.$++q((*Er   c                 ~    [        U R                  R                  5       U R                  UR	                  5       5        g)zfAdd `v` in the end of the vector.

>>> A = AstVector()
>>> len(A)
0
>>> A.push(Int('x'))
>>> len(A)
1
N)Z3_ast_vector_pushrP   rM   r  r   )r   r   s     r   pushAstVector.push  s$     	488<<>4;;
Cr   c                 b    [        U R                  R                  5       U R                  U5        g)zResize the vector to `sz` elements.

>>> A = AstVector()
>>> A.resize(10)
>>> len(A)
10
>>> for i in range(10): A[i] = Int('x')
>>> A[5]
x
N)Z3_ast_vector_resizerP   rM   r  )r   r:  s     r   resizeAstVector.resize  s     	TXX\\^T[["=r   c                 F    U  H  nUR                  U5      (       d  M    g   g)zReturn `True` if the vector contains `item`.

>>> x = Int('x')
>>> A = AstVector()
>>> x in A
False
>>> A.push(x)
>>> x in A
True
>>> (x+1) in A
False
>>> A.push(x+1)
>>> (x+1) in A
True
>>> A
[x, x + 1]
TFr   )r   itemelems      r   __contains__AstVector.__contains__  s#    $ Dwwt}}  r   c                     [        [        U R                  R                  5       U R                  UR                  5       5      US9$ )zCopy vector `self` to context `other_ctx`.

>>> x = Int('x')
>>> A = AstVector()
>>> A.push(x)
>>> c2 = Context()
>>> B = A.translate(c2)
>>> B
[x]
r   )r_   Z3_ast_vector_translaterP   rM   r  r   	other_ctxs     r   r  AstVector.translate  s4     #DHHLLNDKKQ
 	
r   c                 8    U R                  U R                  5      $ r   r  r   s    r   r  AstVector.__copy__  r  r   c                 8    U R                  U R                  5      $ r   r  r   s     r   r   AstVector.__deepcopy__  r  r   c                     [        U 5      $ r   r   r   s    r   r   AstVector.__repr__  r   r   c                 ^    [        U R                  R                  5       U R                  5      $ )zLReturn a textual representation of the s-expression representing the vector.)Z3_ast_vector_to_stringrP   rM   r  r   s    r   r  AstVector.sexpr  s    &txx||~t{{CCr   )rP   r  r  )r   r   r   r   r   r   r   r  r'  r$  r(  r,  r1  r  r  r   r   r  r   r   r   r   r_   r_   V  sO    (	;?D:F 
D>.
 ( !# (#Dr   r_   c                   d    \ rS rSrSrSS jr0 4S jrS rS rS r	S	 r
S
 rS rS rS rS rSrg)AstMapi  zA mapping from ASTs to ASTs.Nc                    S U l         Uc9  [        U5      U l        [        U R                  R	                  5       5      U l         OXl         Uc   eX l        [        U R                  R	                  5       U R                   5        g r   )maprL   rP   Z3_mk_ast_maprM   Z3_ast_map_inc_refr   mrP   s      r   r   AstMap.__init__  s[    9}DH$TXX\\^4DHH?"?H488<<>4884r   c                 B    [        U R                  U R                  5      $ r   )rB  rD  rP   r   s     r   r   AstMap.__deepcopy__  s    dhh))r   c                     U R                   bS  U R                  R                  5       b7  [        b/  [        U R                  R                  5       U R                   5        g g g g r   )rD  rP   rM   Z3_ast_map_dec_refr   s    r   r   AstMap.__del__  sF    88DHHLLN$>CUCatxx||~txx8 Db$>r   c                 p    [        [        U R                  R                  5       U R                  5      5      $ )znReturn the size of the map.

>>> M = AstMap()
>>> len(M)
0
>>> x = Int('x')
>>> M[x] = IntVal(1)
>>> len(M)
1
)r   Z3_ast_map_sizerP   rM   rD  r   s    r   r  AstMap.__len__  s$     ?488<<>488<==r   c                 |    [        U R                  R                  5       U R                  UR	                  5       5      $ )zReturn `True` if the map contains key `key`.

>>> M = AstMap()
>>> x = Int('x')
>>> M[x] = x + 1
>>> x in M
True
>>> x+1 in M
False
)Z3_ast_map_containsrP   rM   rD  r   r   r   s     r   r1  AstMap.__contains__  s'     #488<<>488SZZ\JJr   c                     [        [        U R                  R                  5       U R                  UR                  5       5      U R                  5      $ )zqRetrieve the value associated with key `key`.

>>> M = AstMap()
>>> x = Int('x')
>>> M[x] = x + 1
>>> M[x]
x + 1
)r   Z3_ast_map_findrP   rM   rD  r   rT  s     r   r'  AstMap.__getitem__%  s5     ?488<<>488SZZ\RTXT\T\]]r   c                     [        U R                  R                  5       U R                  UR	                  5       UR	                  5       5        g)zAdd/Update key `k` with value `v`.

>>> M = AstMap()
>>> x = Int('x')
>>> M[x] = x + 1
>>> len(M)
1
>>> M[x]
x + 1
>>> M[x] = IntVal(1)
>>> M[x]
1
N)Z3_ast_map_insertrP   rM   rD  r   )r   r   r   s      r   r$  AstMap.__setitem__0  s,     	$((,,.$((AHHJ
Kr   c                 ^    [        U R                  R                  5       U R                  5      $ r   )Z3_ast_map_to_stringrP   rM   rD  r   s    r   r   AstMap.__repr__@  s    #DHHLLNDHH==r   c                 ~    [        U R                  R                  5       U R                  UR	                  5       5        g)zRemove the entry associated with key `k`.

>>> M = AstMap()
>>> x = Int('x')
>>> M[x] = x + 1
>>> len(M)
1
>>> M.erase(x)
>>> len(M)
0
N)Z3_ast_map_eraserP   rM   rD  r   )r   r   s     r   eraseAstMap.eraseC  s$     	188:>r   c                 `    [        U R                  R                  5       U R                  5        g)zRemove all entries from the map.

>>> M = AstMap()
>>> x = Int('x')
>>> M[x]   = x + 1
>>> M[x+x] = IntVal(1)
>>> len(M)
2
>>> M.reset()
>>> len(M)
0
N)Z3_ast_map_resetrP   rM   rD  r   s    r   resetAstMap.resetQ  s     	2r   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ )zReturn an AstVector containing all keys in the map.

>>> M = AstMap()
>>> x = Int('x')
>>> M[x]   = x + 1
>>> M[x+x] = IntVal(1)
>>> M.keys()
[x, x + x]
)r_   Z3_ast_map_keysrP   rM   rD  r   s    r   keysAstMap.keys`  s*     BDHHMMr   )rP   rD  r  )r   r   r   r   r   r   r   r   r  r1  r'  r$  r   ra  re  ri  r   r   r   r   rB  rB    sE    &	5 !# *9>K	^L >?3
Nr   rB  c                   N    \ rS rSrSrS r0 4S jrS rS rS r	S r
S	 rS
 rSrg)	FuncEntryis  zJStore the value of the interpretation of a function in a particular point.c                 x    Xl         X l        [        U R                  R                  5       U R                   5        g r   )entryrP   Z3_func_entry_inc_refrM   )r   rn  rP   s      r   r   FuncEntry.__init__v  s$    
dhhllndjj9r   c                 B    [        U R                  U R                  5      $ r   )rl  rn  rP   r   s     r   r   FuncEntry.__deepcopy__{  s    TXX..r   c                     U R                   R                  5       b7  [        b/  [        U R                   R                  5       U R                  5        g g g r   )rP   rM   Z3_func_entry_dec_refrn  r   s    r   r   FuncEntry.__del__~  s9    88<<>%*?*K!$((,,.$**= +L%r   c                 p    [        [        U R                  R                  5       U R                  5      5      $ )a&  Return the number of arguments in the given entry.

>>> f = Function('f', IntSort(), IntSort(), IntSort())
>>> s = Solver()
>>> s.add(f(0, 1) == 10, f(1, 2) == 20, f(1, 0) == 10)
>>> s.check()
sat
>>> m = s.model()
>>> f_i = m[f]
>>> f_i.num_entries()
1
>>> e = f_i.entry(0)
>>> e.num_args()
2
)r   Z3_func_entry_get_num_argsrP   rM   rn  r   s    r   r   FuncEntry.num_args  s%      -dhhllndjjIJJr   c                     XR                  5       :  a  [        e[        [        U R                  R                  5       U R                  U5      U R                  5      $ )a  Return the value of argument `idx`.

>>> f = Function('f', IntSort(), IntSort(), IntSort())
>>> s = Solver()
>>> s.add(f(0, 1) == 10, f(1, 2) == 20, f(1, 0) == 10)
>>> s.check()
sat
>>> m = s.model()
>>> f_i = m[f]
>>> f_i.num_entries()
1
>>> e = f_i.entry(0)
>>> e
[1, 2, 20]
>>> e.num_args()
2
>>> e.arg_value(0)
1
>>> e.arg_value(1)
2
>>> try:
...   e.arg_value(2)
... except IndexError:
...   print("index error")
index error
)r   r  rH  Z3_func_entry_get_argrP   rM   rn  r  s     r   	arg_valueFuncEntry.arg_value  sB    6 --/!1$((,,.$**cRTXT\T\]]r   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ )aG  Return the value of the function at point `self`.

>>> f = Function('f', IntSort(), IntSort(), IntSort())
>>> s = Solver()
>>> s.add(f(0, 1) == 10, f(1, 2) == 20, f(1, 0) == 10)
>>> s.check()
sat
>>> m = s.model()
>>> f_i = m[f]
>>> f_i.num_entries()
1
>>> e = f_i.entry(0)
>>> e
[1, 2, 20]
>>> e.num_args()
2
>>> e.value()
20
)rH  Z3_func_entry_get_valuerP   rM   rn  r   s    r   r*   FuncEntry.value  s.    ( 3DHHLLNDJJOQUQYQYZZr   c                     [        U R                  5       5       Vs/ s H  oR                  U5      PM     nnUR                  U R	                  5       5        U$ s  snf )a   Return entry `self` as a Python list.
>>> f = Function('f', IntSort(), IntSort(), IntSort())
>>> s = Solver()
>>> s.add(f(0, 1) == 10, f(1, 2) == 20, f(1, 0) == 10)
>>> s.check()
sat
>>> m = s.model()
>>> f_i = m[f]
>>> f_i.num_entries()
1
>>> e = f_i.entry(0)
>>> e.as_list()
[1, 2, 20]
)r7  r   r{  r  r*   )r   r<  rb   s      r   as_listFuncEntry.as_list  sI     ,1+AB+Aaq!+ABDJJL! Cs   Ac                 4    [        U R                  5       5      $ r   )r   r  r   s    r   r   FuncEntry.__repr__  s    DLLN##r   )rP   rn  N)r   r   r   r   r   r   r   r   r   r{  r*   r  r   r   r   r   r   rl  rl  s  s5    T:
 !# />K$^>[,&$r   rl  c                   `    \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 r0 4S jrS rS rSrg)
FuncInterpi  z6Stores the interpretation of a function in a Z3 model.c                     Xl         X l        U R                   b/  [        U R                  R                  5       U R                   5        g g r   )r  rP   Z3_func_interp_inc_refrM   )r   r  rP   s      r   r   FuncInterp.__init__  s3    66"488<<>466: r   c                     U R                   bS  U R                  R                  5       b7  [        b/  [        U R                  R                  5       U R                   5        g g g g r   )r  rP   rM   Z3_func_interp_dec_refr   s    r   r   FuncInterp.__del__  sF    66$((,,."<AWAc"488<<>466: Bd"<r   c                     [        U R                  R                  5       U R                  5      nU(       a  [	        XR                  5      $ g)a>  
Return the `else` value for a function interpretation.
Return None if Z3 did not specify the `else` value for
this object.

>>> f = Function('f', IntSort(), IntSort())
>>> s = Solver()
>>> s.add(f(0) == 1, f(1) == 1, f(2) == 0)
>>> s.check()
sat
>>> m = s.model()
>>> m[f]
[2 -> 0, else -> 1]
>>> m[f].else_value()
1
N)Z3_func_interp_get_elserP   rM   r  rH  r   r   s     r   
else_valueFuncInterp.else_value  s3    " $DHHLLNDFF;88,,r   c                 p    [        [        U R                  R                  5       U R                  5      5      $ )a  Return the number of entries/points in the function interpretation `self`.

>>> f = Function('f', IntSort(), IntSort())
>>> s = Solver()
>>> s.add(f(0) == 1, f(1) == 1, f(2) == 0)
>>> s.check()
sat
>>> m = s.model()
>>> m[f]
[2 -> 0, else -> 1]
>>> m[f].num_entries()
1
)r   Z3_func_interp_get_num_entriesrP   rM   r  r   s    r   num_entriesFuncInterp.num_entries  s%     1$((,,.$&&IJJr   c                 p    [        [        U R                  R                  5       U R                  5      5      $ )zReturn the number of arguments for each entry in the function interpretation `self`.

>>> f = Function('f', IntSort(), IntSort())
>>> s = Solver()
>>> s.add(f(0) == 1, f(1) == 1, f(2) == 0)
>>> s.check()
sat
>>> m = s.model()
>>> m[f].arity()
1
)r   Z3_func_interp_get_arityrP   rM   r  r   s    r   r  FuncInterp.arity  s%     +DHHLLNDFFCDDr   c                     XR                  5       :  a  [        e[        [        U R                  R                  5       U R                  U5      U R                  5      $ )a:  Return an entry at position `idx < self.num_entries()` in the function interpretation `self`.

>>> f = Function('f', IntSort(), IntSort())
>>> s = Solver()
>>> s.add(f(0) == 1, f(1) == 1, f(2) == 0)
>>> s.check()
sat
>>> m = s.model()
>>> m[f]
[2 -> 0, else -> 1]
>>> m[f].num_entries()
1
>>> m[f].entry(0)
[2, 0]
)r  r  rl  Z3_func_interp_get_entryrP   rM   r  r  s     r   rn  FuncInterp.entry"  sE      ""$$1$((,,.$&&#NPTPXPXYYr   c                     [        [        U R                  R                  5       U R                  UR                  5       5      U5      $ )z2Copy model 'self' to context 'other_ctx'.
        )r  Z3_model_translaterP   rM   r  r5  s     r   r  FuncInterp.translate6  s0     *488<<>4::y}}WYbccr   c                 8    U R                  U R                  5      $ r   r  r   s    r   r  FuncInterp.__copy__;  r  r   c                 8    U R                  U R                  5      $ r   r  r   s     r   r   FuncInterp.__deepcopy__>  r  r   c                     [        U R                  5       5       Vs/ s H!  oR                  U5      R                  5       PM#     nnUR	                  U R                  5       5        U$ s  snf )zReturn the function interpretation as a Python list.
>>> f = Function('f', IntSort(), IntSort())
>>> s = Solver()
>>> s.add(f(0) == 1, f(1) == 1, f(2) == 0)
>>> s.check()
sat
>>> m = s.model()
>>> m[f]
[2 -> 0, else -> 1]
>>> m[f].as_list()
[[2, 0], 1]
)r7  r  rn  r  r  r  )r   r<  r   s      r   r  FuncInterp.as_listA  sU     /4D4D4D4F.GH.GZZ]""$.GH	"# Is   (A'c                     [        U 5      $ r   r   r   s    r   r   FuncInterp.__repr__R  r   r   )rP   r  N)r   r   r   r   r   r   r   r  r  r  rn  r  r  r   r  r   r   r   r   r   r  r    sE    @;;.K EZ(d
( !# ("#r   r  c                       \ rS rSrSrS rS rS rS rSS jr	SS jr
S	 rS
 rS rS rS rS rS rS rS rS rS rS rS r0 4S jrSrg)r  iV  zGModel/Solution of a satisfiability problem (aka system of constraints).c                     Uc   eXl         X l        [        U R                  R                  5       U R                   5        g r   )r  rP   Z3_model_inc_refrM   rG  s      r   r   ModelRef.__init__Y  s.    
4r   c                     U R                   R                  5       b7  [        b/  [        U R                   R                  5       U R                  5        g g g r   )rP   rM   Z3_model_dec_refr  r   s    r   r   ModelRef.__del___  9    88<<>%*:*FTXX\\^TZZ8 +G%r   c                     [        U 5      $ r   r   r   s    r   r   ModelRef.__repr__c  r   r   c                 ^    [        U R                  R                  5       U R                  5      $ )zKReturn a textual representation of the s-expression representing the model.)Z3_model_to_stringrP   rM   r  r   s    r   r  ModelRef.sexprf  s    !$((,,.$**==r   c                     [         S-  " 5       n[        U R                  R                  5       U R                  UR                  5       X#5      (       a  [        US   U R                  5      $ [        S5      e)a  Evaluate the expression `t` in the model `self`.
If `model_completion` is enabled, then a default interpretation is automatically added
for symbols that do not have an interpretation in the model `self`.

>>> x = Int('x')
>>> s = Solver()
>>> s.add(x > 0, x < 2)
>>> s.check()
sat
>>> m = s.model()
>>> m.eval(x + 1)
2
>>> m.eval(x == 1)
True
>>> y = Int('y')
>>> m.eval(y + x)
1 + y
>>> m.eval(y)
y
>>> m.eval(y, model_completion=True)
0
>>> # Now, m contains an interpretation for y
>>> m.eval(y + x)
1
r   r   z*failed to evaluate expression in the model)r?  Z3_model_evalrP   rM   r  r   rH  r9   )r   r	  model_completionr   s       r   evalModelRef.evalj  sV    4 1WKQXXZAQUU!dhh//FGGr   c                 $    U R                  X5      $ )aW  Alias for `eval`.

>>> x = Int('x')
>>> s = Solver()
>>> s.add(x > 0, x < 2)
>>> s.check()
sat
>>> m = s.model()
>>> m.evaluate(x + 1)
2
>>> m.evaluate(x == 1)
True
>>> y = Int('y')
>>> m.evaluate(y + x)
1 + y
>>> m.evaluate(y)
y
>>> m.evaluate(y, model_completion=True)
0
>>> # Now, m contains an interpretation for y
>>> m.evaluate(y + x)
1
)r  )r   r	  r  s      r   evaluateModelRef.evaluate  s    0 yy--r   c                     [        [        U R                  R                  5       U R                  5      5      n[        [        U R                  R                  5       U R                  5      5      nX-   $ )zReturn the number of constant and function declarations in the model `self`.

>>> f = Function('f', IntSort(), IntSort())
>>> x = Int('x')
>>> s = Solver()
>>> s.add(x > 0, f(x) != x)
>>> s.check()
sat
>>> m = s.model()
>>> len(m)
2
)r   Z3_model_get_num_constsrP   rM   r  Z3_model_get_num_funcs)r   
num_consts	num_funcss      r   r  ModelRef.__len__  sM     0LM
.txx||~tzzJK	%%r   c                 B   [        5       (       a,  [        [        U[        5      =(       d    [	        U5      S5        [	        U5      (       a  UR                  5       n UR                  5       S:X  GaR  [        U R                  R                  5       U R                  UR                  5      nUR                  c  g[        X R                  5      n[        U5      (       a  U R                  [!        U5      5      nUc  U$ UR#                  5       nUc  U$ UR                  5       S:w  a  U$ UR%                  5       nUR'                  5       n[)        Xu5      nSnUR+                  5       n	UR                  5       n
X:  aF  UR-                  U5      n[/        X[R1                  S5      UR                  5       5      nUS-  nX:  a  MF  U$ U$ [3        [5        U R                  R                  5       U R                  UR                  5      U R                  5      $ ! [6         a     gf = f)zReturn the interpretation for a given declaration or constant.

>>> f = Function('f', IntSort(), IntSort())
>>> x = Int('x')
>>> s = Solver()
>>> s.add(x > 0, x < 2, f(x) == 0)
>>> s.check()
sat
>>> m = s.model()
>>> m[x]
1
>>> m[f]
[else -> 0]
zZ3 declaration expectedr   Nr   )r   r;   r   r  rc  r  r  Z3_model_get_const_interprP   rM   r  r   r*   rH  is_as_array
get_interpget_as_array_funcr  r7  r  r  r  rn  r  r{  r  Z3_model_get_func_interpr9   )r   r  _rr   firr   srtr  r<  r:  r>   fes               r   r  ModelRef.get_interp  s    ::z$4FHabD>>99;D	zz|q .txx||~tzz488T88# XX.q>>):1)=>Bz!	Ay!	xxzQ!	**,C::<C#	AA)B
A&XXa[!!\\!_bhhjAQ & HH!":488<<>4::W[W_W_"`bfbjbjkk 		s@   AH 9AH =H H (BH  H H AH 
HHc                 p    [        [        U R                  R                  5       U R                  5      5      $ )zReturn the number of uninterpreted sorts that contain an interpretation in the model `self`.

>>> A = DeclareSort('A')
>>> a, b = Consts('a b', A)
>>> s = Solver()
>>> s.add(a != b)
>>> s.check()
sat
>>> m = s.model()
>>> m.num_sorts()
1
)r   Z3_model_get_num_sortsrP   rM   r  r   s    r   	num_sortsModelRef.num_sorts  s%     )$((,,.$**EFFr   c                     XR                  5       :  a  [        e[        [        U R                  R                  5       U R                  U5      U R                  5      $ )aF  Return the uninterpreted sort at position `idx` < self.num_sorts().

>>> A = DeclareSort('A')
>>> B = DeclareSort('B')
>>> a1, a2 = Consts('a1 a2', A)
>>> b1, b2 = Consts('b1 b2', B)
>>> s = Solver()
>>> s.add(a1 != a2, b1 != b2)
>>> s.check()
sat
>>> m = s.model()
>>> m.num_sorts()
2
>>> m.get_sort(0)
A
>>> m.get_sort(1)
B
)r  r  rE  Z3_model_get_sortrP   rM   r  r  s     r   get_sortModelRef.get_sort  sC    & ..""-dhhllndjj#NPTPXPXYYr   c                 |    [        U R                  5       5       Vs/ s H  oR                  U5      PM     sn$ s  snf )a+  Return all uninterpreted sorts that have an interpretation in the model `self`.

>>> A = DeclareSort('A')
>>> B = DeclareSort('B')
>>> a1, a2 = Consts('a1 a2', A)
>>> b1, b2 = Consts('b1 b2', B)
>>> s = Solver()
>>> s.add(a1 != a2, b1 != b2)
>>> s.check()
sat
>>> m = s.model()
>>> m.sorts()
[A, B]
)r7  r  r  r  s     r   r  ModelRef.sorts  s1     +00@*AB*AQa *ABBBs   9c                    [        5       (       a  [        [        U[        5      S5         [	        [        U R                  R                  5       U R                  UR                  5      U R                  5      $ ! [         a     gf = f)zReturn the interpretation for the uninterpreted sort `s` in the model `self`.

>>> A = DeclareSort('A')
>>> a, b = Consts('a b', A)
>>> s = Solver()
>>> s.add(a != b)
>>> s.check()
sat
>>> m = s.model()
>>> m.get_universe(A)
[A!val!1, A!val!0]
r  N)r   r;   r   rM  r_   Z3_model_get_sort_universerP   rM   r  r   r9   r!  s     r   get_universeModelRef.get_universe  sg     ::z!W-/AB	7

TUTYTYZ\`\d\dee 		s   AA8 8
BBc                    [        U5      (       a  U[        U 5      :  a  [        e[        U R                  R                  5       U R                  5      nX:  aC  [        [        U R                  R                  5       U R                  U5      U R                  5      $ [        [        U R                  R                  5       U R                  X-
  5      U R                  5      $ [        U[        5      (       a  U R                  U5      $ [        U5      (       a  U R                  UR                  5       5      $ [        U[        5      (       a  U R                  U5      $ [!        5       (       a  [#        SS5        g)a  If `idx` is an integer, then the declaration at position `idx` in the model `self` is returned.
If `idx` is a declaration, then the actual interpretation is returned.

The elements can be retrieved using position or the actual declaration.

>>> f = Function('f', IntSort(), IntSort())
>>> x = Int('x')
>>> s = Solver()
>>> s.add(x > 0, x < 2, f(x) == 0)
>>> s.check()
sat
>>> m = s.model()
>>> len(m)
2
>>> m[0]
x
>>> m[1]
f
>>> m[x]
1
>>> m[f]
[else -> 0]
>>> for d in m: print("%s -> %s" % (d, m[d]))
x -> 1
f -> [else -> 0]
Fz0Integer, Z3 declaration, or Z3 constant expectedN)r   r[   r  r  rP   rM   r  r  Z3_model_get_const_declZ3_model_get_func_declr   r  rc  r  rM  r  r   r;   )r   r  r  s      r   r'  ModelRef.__getitem__3  s	   6 3<<c$i  0LJ "#:488<<>4::WZ#[]a]e]eff"#9$((,,.$**VYVf#gimiqiqrrc;''??3''C==??388:..c7##$$S))::uPQr   c           
      J   / n[        [        U R                  R                  5       U R                  5      5       HU  nUR                  [        [        U R                  R                  5       U R                  U5      U R                  5      5        MW     [        [        U R                  R                  5       U R                  5      5       HU  nUR                  [        [        U R                  R                  5       U R                  U5      U R                  5      5        MW     U$ )zReturn a list with all symbols that have an interpretation in the model `self`.
>>> f = Function('f', IntSort(), IntSort())
>>> x = Int('x')
>>> s = Solver()
>>> s.add(x > 0, x < 2, f(x) == 0)
>>> s.check()
sat
>>> m = s.model()
>>> m.decls()
[x, f]
)
r7  r  rP   rM   r  r  r  r  r  r  )r   r   r<  s      r   declsModelRef.decls`  s     .txx||~tzzJKAHH[!8UV!WY]YaYabc L-dhhllndjjIJAHH[!7

TU!VX\X`X`ab Kr   c                 B   [        U5      (       a  UR                  5       n[        U5      (       Gaz  UR                  5       S:w  Gae  [	        U[
        5      (       GaO  UR                  n[        UR                  5       U R                  UR                  UR                  5       R                  5      n[        XAR                  5      n[        UR                  5       5       H  nUR                  U5      n[!        UR                  5       UR                  5      n[#        5       n[        U5       H#  n	UR%                  UR'                  U	5      5        M%     [)        UR                  5       UR                  5      n
[+        UR                  5       UR                  UR,                  U
5        M     g[        U5      (       a  UR                  5       S:w  a  [/        S5      e[1        U5      n[3        UR                  5       U R                  UR                  UR                  5        g)z'Update the interpretation of a constantr   Nz/Expecting 0-ary function or constant expression)r\  r  r  r  r   r  r  Z3_add_func_interpr   r  r   r  rP   r7  r  rn  rw  r_   r(  r{  r~  Z3_func_interp_add_entryr  r9   rP  Z3_add_const_interp)r   xr*   fi1fi2r<  rr   r>   r   rC  rn   s              r   update_valueModelRef.update_values  s`   1::A??qwwyA~*UJ2O2O''C$QYY[$**aeeUEUEUEWE[E[\CS%%(C5,,./KKN.qyy{AGGDKqAFF1;;q>* "-aiik177C(ceeQXXsK 0 A!'')q.OPPAIIKQUUEIIFr   c                     [        5       (       a  [        [        U[        5      S5        [	        U R
                  R                  5       U R                  UR                  5       5      n[        X!5      $ )zlTranslate `self` to the context `target`. That is, return a copy of `self` in the context `target`.
        r  )	r   r;   r   ru   r  rP   rM   r  r  )r   r  r  s      r   r  ModelRef.translate  sJ     ::z&'24ST"488<<>4::vzz|L&&r   c           	      >   U R                   R                  5       n[        [        U5      -  " 5       n[	        [        U5      5       H  nX   R                  5       XE'   M     [        [        X0R                  [        U5      XBR                  5      U R                   5      $ )zPerform model-based projection on fml with respect to vars.
Assume that the model satisfies fml. Then compute a projection fml_p, such
that vars do not occur free in fml_p, fml_p is true in the model and
fml_p => exists vars . fml
)
rP   rM   r?  r[   r7  r   rH  Z3_qe_model_projectr  r   )r   varsr.  rP   _varsr<  s         r   projectModelRef.project  sr     hhllns4y#s4y!Aw~~'EH "/ZZTESZSZ[]a]e]effr   c                 p   U R                   R                  5       n[        [        U5      -  " 5       n[	        [        U5      5       H  nX   R                  5       XE'   M     [        5       n[        X0R                  [        U5      XBR                  UR                  5      n[        XpR                   5      nXv4$ )z[Perform model-based projection, but also include realizer terms for the projected variables)rP   rM   r?  r[   r7  r   rB   Z3_qe_model_project_with_witnessr  r   rD  rH  )r   r  r.  rP   r  r<  defsr  s           r   project_with_witnessModelRef.project_with_witness  s    hhllns4y#s4y!Aw~~'EH "x1#zz3t9eU\U\^b^f^fgfhh/|r   c                 8    U R                  U R                  5      $ r   r  r   s    r   r  ModelRef.__copy__  r  r   c                 8    U R                  U R                  5      $ r   r  r   s     r   r   ModelRef.__deepcopy__  r  r   )rP   r  NF)r   r   r   r   r   r   r   r   r  r  r  r  r  r  r  r  r  r'  r  r  r  r  r  r  r   r   r   r   r   r  r  V  sv    Q59#>H>.4&"2hGZ.C"(+Z&G,'
g	( !# (r   r  c                     [        U 5      n [        [        U R                  5       5      U 5      nUR	                  5        H  u  p4UR                  X45        M     U$ r   )rL   r  Z3_mk_modelrM   itemsr  )rP   r  mdlr   r   s        r   Modelr    sG    
3-C
;swwy)3
/C

 Jr   c                     [        U [        5      =(       a2    [        U R                  R	                  5       U R                  5       5      $ )z?Return true if n is a Z3 expression of the form (_ as-array f).)r   r  Z3_is_as_arrayrP   rM   r   r>   s    r   r  r    s+    a!MnQUUYY[!((*&MMr   c                     [        5       (       a  [        [        U 5      S5        [        [	        U R
                  R                  5       U R                  5       5      U R
                  5      $ )z]Return the function declaration f associated with a Z3 expression of the form (_ as-array f).z as-array Z3 expression expected.)r   r;   r  r  Z3_get_as_array_func_declrP   rM   r   r  s    r   r  r    sA    zz;q>#EF0ahhjI155QQr   c                   T    \ rS rSrSrS r0 4S jrS rS rS r	S r
S	 rS
 rS rSrg)
Statisticsi  z Statistics for `Solver.check()`.c                 x    Xl         X l        [        U R                  R                  5       U R                   5        g r   )statsrP   Z3_stats_inc_refrM   )r   r
  rP   s      r   r   Statistics.__init__  s$    
4r   c                 B    [        U R                  U R                  5      $ r   )r  r
  rP   r   s     r   r   Statistics.__deepcopy__  s    $**dhh//r   c                     U R                   R                  5       b7  [        b/  [        U R                   R                  5       U R                  5        g g g r   )rP   rM   Z3_stats_dec_refr
  r   s    r   r   Statistics.__del__  r  r   c           
         [        5       (       a  [        R                  " 5       nSnUR                  [	        S5      5        U  Hh  u  p4U(       a  UR                  [	        S5      5        SnOUR                  [	        S5      5        SnUR                  [	        SU< SU< S35      5        Mj     UR                  [	        S	5      5        UR                  5       $ [        U R                  R                  5       U R                  5      $ )
NT2<table border="1" cellpadding="2" cellspacing="0">%<tr style="background-color:#CFCFCF">F<tr><td>	</td><td>
</td></tr></table>)
r   ioStringIOwriteugetvalueZ3_stats_to_stringrP   rM   r
  )r   r>  evenr   r   s        r   r   Statistics.__repr__  s    >>++-CDIIaLMNIIa GHI DIIai(D		!QBCD  IIa
m$<<>!%dhhllndjjAAr   c                 p    [        [        U R                  R                  5       U R                  5      5      $ )zReturn the number of statistical counters.

>>> x = Int('x')
>>> s = Then('simplify', 'nlsat').solver()
>>> s.add(x > 0)
>>> s.check()
sat
>>> st = s.statistics()
>>> len(st)
7
)r   Z3_stats_sizerP   rM   r
  r   s    r   r  Statistics.__len__  s$     =<==r   c                    U[        U 5      :  a  [        e[        U R                  R	                  5       U R
                  U5      (       a9  [        [        U R                  R	                  5       U R
                  U5      5      nO/[        U R                  R	                  5       U R
                  U5      n[        U R                  R	                  5       U R
                  U5      U4$ )a(  Return the value of statistical counter at position `idx`. The result is a pair (key, value).

>>> x = Int('x')
>>> s = Then('simplify', 'nlsat').solver()
>>> s.add(x > 0)
>>> s.check()
sat
>>> st = s.statistics()
>>> len(st)
7
>>> st[0]
('nlsat propagations', 2)
>>> st[1]
('nlsat restarts', 1)
)
r[   r  Z3_stats_is_uintrP   rM   r
  r   Z3_stats_get_uint_valueZ3_stats_get_double_valueZ3_stats_get_key)r   r  rn   s      r   r'  Statistics.__getitem__  s      #d)DHHLLNDJJ<<-dhhllndjj#NOC+DHHLLNDJJLC SA3GGr   c                     [        [        U 5      5       Vs/ s H2  n[        U R                  R	                  5       U R
                  U5      PM4     sn$ s  snf )zReturn the list of statistical counters.

>>> x = Int('x')
>>> s = Then('simplify', 'nlsat').solver()
>>> s.add(x > 0)
>>> s.check()
sat
>>> st = s.statistics()
)r7  r[   r)  rP   rM   r
  r  s     r   ri  Statistics.keys  sD     NSSVW[S\M]^M]c SAM]^^^s   9Ac                    [        [        U 5      5       H  nU[        U R                  R	                  5       U R
                  U5      :X  d  M8  [        U R                  R	                  5       U R
                  U5      (       a:  [        [        U R                  R	                  5       U R
                  U5      5      s  $ [        U R                  R	                  5       U R
                  U5      s  $    [        S5      e)zReturn the value of a particular statistical counter.

>>> x = Int('x')
>>> s = Then('simplify', 'nlsat').solver()
>>> s.add(x > 0)
>>> s.check()
sat
>>> st = s.statistics()
>>> st.get_key_value('nlsat propagations')
2
zunknown key)r7  r[   r)  rP   rM   r
  r&  r   r'  r(  r9   )r   r   r  s      r   get_key_valueStatistics.get_key_value  s     T#C&txx||~tzz3GG#DHHLLNDJJDD6txx||~tzzSVWXX4TXX\\^TZZQTUU $ -((r   c                 r    UR                  SS5      n U R                  U5      $ ! [         a    [        ef = f)a_  Access the value of statistical using attributes.

Remark: to access a counter containing blank spaces (e.g., 'nlsat propagations'),
we should use '_' (e.g., 'nlsat_propagations').

>>> x = Int('x')
>>> s = Then('simplify', 'nlsat').solver()
>>> s.add(x > 0)
>>> s.check()
sat
>>> st = s.statistics()
>>> st.nlsat_propagations
2
>>> st.nlsat_stages
2
_r|  )replacer.  r9   AttributeError)r   r?   r   s      r   __getattr__Statistics.__getattr__1  s?    " ll3$	!%%c** 	!  	!s   % 6)rP   r
  N)r   r   r   r   r   r   r   r   r   r  r'  ri  r.  r4  r   r   r   r   r  r    s:    *5
 !# 09B$>H0
_)(!r   r  c                   B    \ rS rSrSrS r0 4S jrS rS rS r	S r
S	rg
)CheckSatResultiO  zRepresents the result of a satisfiability check: sat, unsat, unknown.

>>> s = Solver()
>>> s.check()
sat
>>> r = s.check()
>>> isinstance(r, CheckSatResult)
True
c                     Xl         g r   r   r  s     r   r   CheckSatResult.__init__Z  s    r   c                 ,    [        U R                  5      $ r   )r7  r   r   s     r   r   CheckSatResult.__deepcopy__]  s    dff%%r   c                 b    [        U[        5      =(       a    U R                  UR                  :H  $ r   )r   r7  r   r   s     r   r   CheckSatResult.__eq__`  s!    %0FTVVuww5FFr   c                 .    U R                  U5      (       + $ r   )r   r   s     r   ri  CheckSatResult.__ne__c  s    ;;u%%%r   c                     [        5       (       a+  U R                  [        :X  a  gU R                  [        :X  a  ggU R                  [        :X  a  gU R                  [        :X  a  gg)Nz
<b>sat</b>z<b>unsat</b>z<b>unknown</b>satunsatunknown)r   r   	Z3_L_TRUE
Z3_L_FALSEr   s    r   r   CheckSatResult.__repr__f  sK    >>vv"#:%%'vv":% r   c                 \    [        5       n[        S5        [        U 5      n[        U5        U$ r   r   r   s      r   r   CheckSatResult._repr_html_v  r   r   r9  N)r   r   r   r   r   r   r   r   ri  r   r   r   r   r   r   r7  r7  O  s+     !# &G&! r   r7  c                   H   \ rS rSrSrS4S jrS rS rS rS r	S	 r
S5S
 jrS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS rS6S jrS rS rS rS r S  r!S! r"S" r#S# r$S$ r%S% r&S& r'S' r(S( r)S) r*S* r+S+ r,S, r-S- r.S. r/0 4S/ jr0S0 r1S7S1 jr2S2 r3S3r4g)8r&  i  zk
Solver API provides methods for implementing the main SMT 2.0 commands:
push, pop, check, get-model, etc.
Nc                 <   Ub  Uc   e[        U5      U l        SU l        S U l        Uc)  [	        U R                  R                  5       5      U l        OXl        [        U R                  R                  5       U R                  5        Ub  U R                  SU5        g g )N    (\ smtlib2_log)rL   rP   backtrack_levelsolverZ3_mk_solverrM   Z3_solver_inc_refr^   )r   rO  rP   logFiles       r   r   Solver.__init__  s|    ~00C=)>&txx||~6DK K$((,,.$++6HH]G, r   c                     U R                   bS  U R                  R                  5       b7  [        b/  [        U R                  R                  5       U R                   5        g g g g r   )rO  rP   rM   Z3_solver_dec_refr   s    r   r   Solver.__del__  F    ;;"txx||~'AFWFcdhhllndkk: Gd'A"r   c                 &    U R                  5         U $ r   r(  r   s    r   	__enter__Solver.__enter__      		r   c                 $    U R                  5         g r   popr   exc_infos     r   __exit__Solver.__exit__      
r   c                     [        XU R                  5      n[        U R                  R                  5       U R                  UR
                  5        g)zSet a configuration option.
The method `help()` return a string containing all available options.

>>> s = Solver()
>>> # The option MBQI can be set using three different approaches.
>>> s.set(mbqi=True)
>>> s.set('MBQI', True)
>>> s.set(':mbqi', True)
N)r  rP   Z3_solver_set_paramsrM   rO  r  r   rb   ri  r`  s       r   r^   
Solver.set  s2     DHH-TXX\\^T[[!((Cr   c                 `    [        U R                  R                  5       U R                  5        g)zCreate a backtracking point.

>>> x = Int('x')
>>> s = Solver()
>>> s.add(x > 0)
>>> s
[x > 0]
>>> s.push()
>>> s.add(x < 1)
>>> s
[x > 0, x < 1]
>>> s.check()
unsat
>>> s.pop()
>>> s.check()
sat
>>> s
[x > 0]
N)Z3_solver_pushrP   rM   rO  r   s    r   r(  Solver.push  s    ( 	txx||~t{{3r   c                 b    [        U R                  R                  5       U R                  U5        g)zBacktrack \c num backtracking points.

>>> x = Int('x')
>>> s = Solver()
>>> s.add(x > 0)
>>> s
[x > 0]
>>> s.push()
>>> s.add(x < 1)
>>> s
[x > 0, x < 1]
>>> s.check()
unsat
>>> s.pop()
>>> s.check()
sat
>>> s
[x > 0]
N)Z3_solver_poprP   rM   rO  )r   r  s     r   r_  
Solver.pop  s    ( 	dhhllndkk37r   c                 ^    [        U R                  R                  5       U R                  5      $ )zReturn the current number of backtracking points.

>>> s = Solver()
>>> s.num_scopes()
0
>>> s.push()
>>> s.num_scopes()
1
>>> s.push()
>>> s.num_scopes()
2
>>> s.pop()
>>> s.num_scopes()
1
)Z3_solver_get_num_scopesrP   rM   rO  r   s    r   
num_scopesSolver.num_scopes  s      (DDr   c                 `    [        U R                  R                  5       U R                  5        g)zRemove all asserted constraints and backtracking points created using `push()`.

>>> x = Int('x')
>>> s = Solver()
>>> s.add(x > 0)
>>> s
[x > 0]
>>> s.reset()
>>> s
[]
N)Z3_solver_resetrP   rM   rO  r   s    r   re  Solver.reset  s     	4r   c                    [        U5      n[        U R                  5      nU H  n[        U[        5      (       d  [        U[
        5      (       aH  U H@  n[        U R                  R                  5       U R                  UR                  5       5        MB     Mu  UR                  U5      n[        U R                  R                  5       U R                  UR                  5       5        M     g)z}Assert constraints into the solver.

>>> x = Int('x')
>>> s = Solver()
>>> s.assert_exprs(x > 0, x < 2)
>>> s
[x > 0, x < 2]
N)rd   r'  rP   r   r  r_   Z3_solver_assertrM   rO  r   r_  r   rb   rH   rc   r  s        r   r  Solver.assert_exprs  s     TXXC#t$$
3	(B(BA$TXX\\^T[[!((*M  ffSk cjjlK r   c                 "    U R                   " U6   g)ztAssert constraints into the solver.

>>> x = Int('x')
>>> s = Solver()
>>> s.add(x > 0, x < 2)
>>> s
[x > 0, x < 2]
Nr  r  s     r   r(  
Solver.add  r  r   c                 (    U R                  U5        U $ r   r(  r   r.  s     r   __iadd__Solver.__iadd__      r   c                 "    U R                   " U6   g)zwAssert constraints into the solver.

>>> x = Int('x')
>>> s = Solver()
>>> s.append(x > 0, x < 2)
>>> s
[x > 0, x < 2]
Nr  r  s     r   r  Solver.append  r  r   c                 "    U R                   " U6   g)zwAssert constraints into the solver.

>>> x = Int('x')
>>> s = Solver()
>>> s.insert(x > 0, x < 2)
>>> s
[x > 0, x < 2]
Nr  r  s     r   r  Solver.insert'  r  r   c                 |   [        U[        5      (       a  [        X R                  5      n[	        [        U[
        5      S5        [	        [        U[
        5      =(       a    [        U5      S5        [        U R                  R                  5       U R                  UR                  5       UR                  5       5        g)a  Assert constraint `a` and track it in the unsat core using the Boolean constant `p`.

If `p` is a string, it will be automatically converted into a Boolean constant.

>>> x = Int('x')
>>> p3 = Bool('p3')
>>> s = Solver()
>>> s.set(unsat_core=True)
>>> s.assert_and_track(x > 0,  'p1')
>>> s.assert_and_track(x != 1, 'p2')
>>> s.assert_and_track(x < 0,  p3)
>>> print(s.check())
unsat
>>> c = s.unsat_core()
>>> len(c)
2
>>> Bool('p1') in c
True
>>> Bool('p2') in c
False
>>> p3 in c
True
Boolean expression expectedN)r   rl   r  rP   r;   r  rc  Z3_solver_assert_and_trackrM   rO  r   r   r   r`  s      r   assert_and_trackSolver.assert_and_track2  st    0 aQ!A:a)+HI:a)9hqk;XY"488<<>4;;
AHHJWr   c                 R   [        U R                  5      n[        U5      n[        U5      n[        U-  " 5       n[        U5       H&  nUR                  X   5      R                  5       XE'   M(     [        U R                  R                  5       U R                  X45      n[        U5      $ )a;  Check whether the assertions in the given solver plus the optional assumptions are consistent or not.

>>> x = Int('x')
>>> s = Solver()
>>> s.check()
sat
>>> s.add(x > 0, x < 2)
>>> s.check()
sat
>>> s.model().eval(x)
1
>>> s.add(x < 1)
>>> s.check()
unsat
>>> s.reset()
>>> s.add(2**x == 4)
>>> s.check()
unknown
)r'  rP   rd   r[   r?  r7  r_  r   Z3_solver_check_assumptionsrM   rO  r7  )r   assumptionsrH   r  _assumptionsr<  r   s          r   checkSolver.checkP  s    ( TXX,+c	}sAff[^4;;=LO 'SWa  r   c                      [        [        U R                  R                  5       U R                  5      U R                  5      $ ! [
         a    [        S5      ef = f)zReturn a model for the last `check()`.

This function raises an exception if
a model is not available (e.g., last `check()` returned unsat).

>>> s = Solver()
>>> a = Int('a')
>>> s.add(a + 2 == 0)
>>> s.check()
sat
>>> s.model()
[a = -2]
model is not available)r  Z3_solver_get_modelrP   rM   rO  r9   r   s    r   r  Solver.modelm  sI    	8/LdhhWW 	8677	8   AA Ac                 v    [        U R                  R                  5       UR                  U R                  5        g)z9Import model converter from other into the current solverN) Z3_solver_import_model_converterrP   rM   rO  r   s     r   import_model_converterSolver.import_model_converter  s     (t{{Sr   c                 `    [        U R                  R                  5       U R                  5        g)zInterrupt the execution of the solver object.
Remarks: This ensures that the interrupt applies only
to the given solver object and it applies only if it is running.
N)Z3_solver_interruptrP   rM   rO  r   s    r   r   Solver.interrupt  s    
 	DHHLLNDKK8r   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ )a  Return a subset (as an AST vector) of the assumptions provided to the last check().

These are the assumptions Z3 used in the unsatisfiability proof.
Assumptions are available in Z3. They are used to extract unsatisfiable cores.
They may be also used to "retract" assumptions. Note that, assumptions are not really
"soft constraints", but they can be used to implement them.

>>> p1, p2, p3 = Bools('p1 p2 p3')
>>> x, y       = Ints('x y')
>>> s          = Solver()
>>> s.add(Implies(p1, x > 0))
>>> s.add(Implies(p2, y > x))
>>> s.add(Implies(p2, y < 1))
>>> s.add(Implies(p3, y > -3))
>>> s.check(p1, p2, p3)
unsat
>>> core = s.unsat_core()
>>> len(core)
2
>>> p1 in core
True
>>> p2 in core
True
>>> p3 in core
False
>>> # "Retracting" p2
>>> s.check(p1, p3)
sat
)r_   Z3_solver_get_unsat_corerP   rM   rO  r   s    r   
unsat_coreSolver.unsat_core  s.    < 1$((,,.$++NPTPXPXYYr   c                    [        U[        5      (       a2  [        SU R                  5      nU H  nUR	                  U5        M     Un[        U[        5      (       a2  [        SU R                  5      nU H  nUR	                  U5        M     Un[        [        U[        5      S5        [        [        U[        5      S5        [        SU R                  5      n[        U R                  R                  5       U R                  UR                  UR                  UR                  5      n[        U5      n[        U5       V	s/ s H  oU	   PM	     nn	[        U5      U4$ s  sn	f )a  Determine fixed values for the variables based on the solver state and assumptions.
>>> s = Solver()
>>> a, b, c, d = Bools('a b c d')
>>> s.add(Implies(a,b), Implies(b, c))
>>> s.consequences([a],[b,c,d])
(sat, [Implies(a, b), Implies(a, c)])
>>> s.consequences([Not(c),d],[a,b,c,d])
(sat, [Implies(d, d), Implies(Not(c), Not(c)), Implies(Not(c), Not(b)), Implies(Not(c), Not(a))])
Nzast vector expected)r   r]   r_   rP   r(  r;   Z3_solver_get_consequencesrM   rO  r  r[   r7  r7  )
r   r  	variables_asmsr   r  consequencesr   r:  r<  s
             r   r  Solver.consequences  s    k4((dDHH-E 

1 !Ki&&dDHH-E

1 I:k957LM:i35JK txx0&txx||~t{{KDVDV'0'7'79L9LN16r;AQ;a ,.. <s    Ec                 b    [        U R                  R                  5       U R                  U5        g)zParse assertions from a fileN)Z3_solver_from_filerP   rM   rO  r   filenames     r   	from_fileSolver.from_file  s    DHHLLNDKKBr   c                 b    [        U R                  R                  5       U R                  U5        g)zParse assertions from a stringN)Z3_solver_from_stringrP   rM   rO  r!  s     r   r"  Solver.from_string  s    dhhllndkk1=r   c              #     #    [        SU R                  5      U l        Ub$  U H  nU R                  R                  U5        M       U R                  nSU l        [        [        U R                  R                  5       U R                  U R                  R                  U5      U R                  5      n[        U5      S:X  a  [        US   5      (       a  gUv   [        U5      S:X  a  gM  7f)zGet set of cubes
The method takes an optional set of variables that restrict which
variables may be used as a starting point for cubing.
If vars is not None, then the first case split is based on a variable in
this set.
NrL  r   r   )r_   rP   cube_vsr(  rN  Z3_solver_cuberM   rO  r  r[   r   )r   r  r   lvlr   s        r   cubeSolver.cube  s      !txx0!!!$ &&C#-D .dllFYFY[^_aeaiaijAA!1GA! s   C(C*c                     U R                   $ )a  Access the set of variables that were touched by the most recently generated cube.
This set of variables can be used as a starting point for additional cubes.
The idea is that variables that appear in clauses that are reduced by the most recent
cube are likely more useful to cube on.)r  r   s    r   	cube_varsSolver.cube_vars  s    
 ||r   c                     [        XR                  5      n[        [        U R                  R	                  5       U R
                  UR                  5      U R                  5      $ )zRetrieve congruence closure root of the term t relative to the current search state
The function primarily works for SimpleSolver. Terms and variables that are
eliminated during pre-processing are not visible to the congruence closure.
)rP  rP   rH  Z3_solver_congruence_rootrM   rO  r   r   r	  s     r   rootSolver.root  E    
 Q!5dhhllndkkSTSXSXY[_[c[cddr   c                     [        XR                  5      n[        [        U R                  R	                  5       U R
                  UR                  5      U R                  5      $ )zRetrieve congruence closure sibling of the term t relative to the current search state
The function primarily works for SimpleSolver. Terms and variables that are
eliminated during pre-processing are not visible to the congruence closure.
)rP  rP   rH  Z3_solver_congruence_nextrM   rO  r   r  s     r   nextSolver.next  r  r   c                    [        XR                  5      n[        X R                  5      n[        [        U R                  R	                  5       U R
                  UR                  UR                  5      U R                  5      $ )zBExplain congruence of a and b relative to the current search state)rP  rP   rH  Z3_solver_congruence_explainrM   rO  r   )r   r   r&  s      r   explain_congruentSolver.explain_congruent  sZ    Q!Q!8VWV[V[]^]b]bceiememnnr   c                    [        U R                  S9n[        U R                  S9n[        U R                  S9nU H)  n[        XPR                  5      nUR                  U5        M+     [	        U R                  R                  5       U R                  UR                  UR                  UR                  5        [        [        U5      5       Vs/ s H  obU   X6   XF   4PM     sn$ s  snf )zWRetrieve a solution for t relative to linear equations maintained in the current state.r   )
r_   rP   rP  r(  Z3_solver_solve_forrM   rO  r  r7  r[   )r   tsr  termsguardsr	  r<  s          r   	solve_forSolver.solve_for  s    TXX&dhh'txx(AHH%AIIaL  	DHHLLNDKKellTZTaTab8=c$i8HI8H1a%(FI.8HIIIs   C&c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ )zJReturn a proof for the last `check()`. Proof construction must be enabled.)rH  Z3_solver_get_proofrP   rM   rO  r   s    r   proofSolver.proof  s)    /LdhhWWr   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ )zReturn an AST vector containing all added constraints.

>>> s = Solver()
>>> s.assertions()
[]
>>> a = Int('a')
>>> s.add(a > 0)
>>> s.add(a < 10)
>>> s.assertions()
[a > 0, a < 10]
)r_   Z3_solver_get_assertionsrP   rM   rO  r   s    r   r,  Solver.assertions  s.     1$((,,.$++NPTPXPXYYr   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ )zFReturn an AST vector containing all currently inferred units.
        )r_   Z3_solver_get_unitsrP   rM   rO  r   s    r   unitsSolver.units!  +     ,TXX\\^T[[I488TTr   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ )z`Return an AST vector containing all atomic formulas in solver state that are not units.
        )r_   Z3_solver_get_non_unitsrP   rM   rO  r   s    r   	non_unitsSolver.non_units&  s+     0MtxxXXr   c                     U R                  5       n[        R                  [        U5      -  " 5       n[	        U R
                  R                  5       U R                  UR                  [        U5      U5        X4$ )zSReturn trail and decision levels of the solver state after a check() call.
        )	trailr'   r(   r[   Z3_solver_get_levelsrP   rM   rO  r  )r   r  levelss      r   trail_levelsSolver.trail_levels+  sS     

--#e*,/TXX\\^T[[%,,E
TZ[}r   c                     UR                  5       nUR                  U5      n[        U R                  R	                  5       U R
                  UR                  UR                  5        gzSinitialize the solver's state by setting the initial value of var to value
        N)r]  r_  Z3_solver_set_initial_valuerP   rM   rO  r   r   varr*   rH   s       r   set_initial_valueSolver.set_initial_value3  s@     HHJu#DHHLLNDKK%))Tr   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ )z?Return trail of the solver state after a check() call.
        )r_   Z3_solver_get_trailrP   rM   rO  r   s    r   r  Solver.trail:  r  r   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ )zReturn statistics for the last `check()`.

>>> s = SimpleSolver()
>>> x = Int('x')
>>> s.add(x > 0)
>>> s.check()
sat
>>> st = s.statistics()
>>> st.get_key_value('final checks')
1
>>> len(st) > 0
True
>>> st[0] != 0
True
)r  Z3_solver_get_statisticsrP   rM   rO  r   s    r   
statisticsSolver.statistics?  s.      2488<<>4;;OQUQYQYZZr   c                 ^    [        U R                  R                  5       U R                  5      $ )zReturn a string describing why the last `check()` returned `unknown`.

>>> x = Int('x')
>>> s = SimpleSolver()
>>> s.add(2**x == 4)
>>> s.check()
unknown
>>> s.reason_unknown()
'(incomplete (theory arithmetic))'
)Z3_solver_get_reason_unknownrP   rM   rO  r   s    r   reason_unknownSolver.reason_unknownQ  s     ,DHHLLNDKKHHr   c                 r    [        [        U R                  R                  5       U R                  5      5        gz2Display a string describing all available options.N)printZ3_solver_get_helprP   rM   rO  r   s    r   helpSolver.help^        =>r   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ z%Return the parameter description set.)r   Z3_solver_get_param_descrsrP   rM   rO  r   s    r   r   Solver.param_descrsb  ,    8UW[W_W_``r   c                     [        U 5      $ )z5Return a formatted string with all added constraints.r   r   s    r   r   Solver.__repr__f  s    T""r   c                     [        5       (       a  [        [        U[        5      S5        [	        U R
                  R                  5       U R                  UR                  5       5      n[        X!5      $ )zTranslate `self` to the context `target`. That is, return a copy of `self` in the context `target`.

>>> c1 = Context()
>>> c2 = Context()
>>> s1 = Solver(ctx=c1)
>>> s2 = s1.translate(c2)
r  )	r   r;   r   ru   Z3_solver_translaterP   rM   rO  r&  )r   r  rO  s      r   r  Solver.translatej  sJ     ::z&'24ST$TXX\\^T[[&**,Of%%r   c                 8    U R                  U R                  5      $ r   r  r   s    r   r  Solver.__copy__w  r  r   c                 8    U R                  U R                  5      $ r   r  r   s     r   r   Solver.__deepcopy__z  r  r   c                 ^    [        U R                  R                  5       U R                  5      $ )zReturn a formatted string (in Lisp-like format) with all added constraints.
We say the string is in s-expression format.

>>> x = Int('x')
>>> s = Solver()
>>> s.add(x > 0)
>>> s.add(x < 2)
>>> r = s.sexpr()
)Z3_solver_to_stringrP   rM   rO  r   s    r   r  Solver.sexpr}  s     #488<<>4;;??r   c                 `    [        U R                  R                  5       U R                  U5      $ )z?Return a textual representation of the solver in DIMACS format.)Z3_solver_to_dimacs_stringrP   rM   rO  r  s     r   r  Solver.dimacs  s    )$((,,.$++}UUr   c           
         U R                  5       n[        U5      nUnUS:  a  US-  n[        U-  " 5       n[        U5       H  nX   R	                  5       XE'   M     US:  a  X   R	                  5       nO$[        SU R                  5      R	                  5       n[        U R                  R                  5       SSSSX4U5      $ )z:return SMTLIB2 formatted benchmark for solver's assertionsr   r   Tz#benchmark generated from python APIrY  rD  )	r,  r[   r?  r7  r   r  rP   Z3_benchmark_to_smtlib_stringrM   )r   esr:  sz1r   r<  rr   s          r   to_smt2Solver.to_smt2  s    __W71HC3YMsA5<<>AD 6 Adhh'..0A,HHLLNA2yRTVY^_
 	
r   )rN  rP   r  rO  NNN)r   r   r  )5r   r   r   r   r   r   r   rZ  rb  r^   r(  r_  rq  re  r  r(  r  r  r  r  r  r  r  r   r  r  r  r"  r  r  r  r  r  r  r  r,  r  r  r  r  r  r  r  r  r   r   r  r  r   r  r  r	  r   r   r   r   r&  r&    s   
-;D4,8,E$5L&	!	!	!X<!:8&T9Z@/:C>*eeo	JXZU
Y
UU
[$I?a#&( !# (
@V
r   r&  c                 v    [        U5      n[        U 5      n [        [        UR	                  5       U 5      X5      $ )a@  Create a solver customized for the given logic.

The parameter `logic` is a string. It should be contains
the name of a SMT-LIB logic.
See http://www.smtlib.org/ for the name of all available logics.

>>> s = SolverFor("QF_LIA")
>>> x = Int('x')
>>> s.add(x > 0)
>>> s.add(x < 2)
>>> s.check()
sat
>>> s.model()
[x = 1]
)rL   rQ   r&  Z3_mk_solver_for_logicrM   )logicrP   rR  s      r   	SolverForr	    s2      3-CeE(E:CIIr   c                 ^    [        U 5      n [        [        U R                  5       5      X5      $ )zReturn a simple general purpose solver with limited amount of preprocessing.

>>> s = SimpleSolver()
>>> x = Int('x')
>>> s.add(x > 0)
>>> s.check()
sat
)rL   r&  Z3_mk_simple_solverrM   )rP   rR  s     r   SimpleSolverr	    s&     3-C%cggi0#??r   c                      \ rS rSrSrS*S jr0 4S jrS rS rS r	S	 r
S
 rS rS rS rS rS*S jrS*S jrS+S jrS rS rS rS rS rS rS rS rS rS rS rS rS rS r S  r!S! r"S" r#S# r$S$ r%S% r&S& r'S' r(S,S( jr)S)r*g)-
Fixedpointi  zEFixedpoint API provides methods for solving with recursive predicatesNc                    Ub  Uc   e[        U5      U l        S U l        Uc)  [        U R                  R	                  5       5      U l        OXl        [        U R                  R	                  5       U R                  5        / U l        g r   )rL   rP   
fixedpointZ3_mk_fixedpointrM   Z3_fixedpoint_inc_refr  )r   r#	  rP   s      r   r   Fixedpoint.__init__  sd    !S_44C=.txx||~>DO(Odhhllndoo>	r   c                 B    [        U R                  U R                  5      $ r   )
FixedPointr#	  rP   r   s     r   r   Fixedpoint.__deepcopy__      $//48844r   c                     U R                   bS  U R                  R                  5       b7  [        b/  [        U R                  R                  5       U R                   5        g g g g r   )r#	  rP   rM   Z3_fixedpoint_dec_refr   s    r   r   Fixedpoint.__del__  F    ??&488<<>+EJ_Jk!$((,,.$//B Kl+E&r   c                     [        XU R                  5      n[        U R                  R                  5       U R                  UR
                  5        g)zjSet a configuration option. The method `help()` return a string containing all available options.
        N)r  rP   Z3_fixedpoint_set_paramsrM   r#	  r  rg  s       r   r^   Fixedpoint.set  s2     DHH- !((Kr   c                 r    [        [        U R                  R                  5       U R                  5      5        gr  )r  Z3_fixedpoint_get_helprP   rM   r#	  r   s    r   r  Fixedpoint.help       $TXX\\^T__EFr   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ r  )r   Z3_fixedpoint_get_param_descrsrP   rM   r#	  r   s    r   r   Fixedpoint.param_descrs  ,    <TXX\\^T__]_c_g_ghhr   c                    [        U5      n[        U R                  5      nU H  n[        U[        5      (       d  [        U[
        5      (       aY  U HQ  nU R                  U5      n[        U R                  R                  5       U R                  UR                  5       5        MS     M  UR                  U5      nU R                  U5      n[        U R                  R                  5       U R                  UR                  5       5        M     g)zBAssert constraints as background axioms for the fixedpoint solver.N)rd   r'  rP   r   r  r_   abstractZ3_fixedpoint_assertrM   r#	  r   r_  rx  s        r   r  Fixedpoint.assert_exprs  s    TXXC#t$$
3	(B(BAa(A(!((*U  ffSkmmC($TXX\\^T__cjjlS r   c                 "    U R                   " U6   gzYAssert constraints as background axioms for the fixedpoint solver. Alias for assert_expr.Nr  r  s     r   r(  Fixedpoint.add      4 r   c                 (    U R                  U5        U $ r   r}  r~  s     r   r  Fixedpoint.__iadd__  r  r   c                 "    U R                   " U6   gr?	  r  r  s     r   r  Fixedpoint.append  rA	  r   c                 "    U R                   " U6   gr?	  r  r  s     r   r  Fixedpoint.insert  rA	  r   c                    Uc  Sn[        X0R                  5      nUcP  U R                  U5      n[        U R                  R	                  5       U R
                  UR                  5       U5        g[        U5      nU R                  [        [        X R                  5      U5      5      n[        U R                  R	                  5       U R
                  UR                  5       U5        g)zAssert rules defining recursive predicates to the fixedpoint solver.
>>> a = Bool('a')
>>> b = Bool('b')
>>> s = Fixedpoint()
>>> s.register_relation(a.decl())
>>> s.register_relation(b.decl())
>>> s.fact(a)
>>> s.rule(b, a)
>>> s.query(b)
sat
NrY  )
rQ   rP   r;	  Z3_fixedpoint_add_rulerM   r#	  r   rd   r  r  r   headr  r?   r  s        r   add_ruleFixedpoint.add_rule	  s     <Dxx(<==&D"488<<>4??DKKMSWXT?Dgc$&94@AA"488<<>4??AHHJPTUr   c                 (    U R                  XU5        g)zXAssert rules defining recursive predicates to the fixedpoint solver. Alias for add_rule.NrL	  )r   rK	  r  r?   s       r   ruleFixedpoint.rule   s    d$'r   c                 *    U R                  USU5        g)zXAssert facts defining recursive predicates to the fixedpoint solver. Alias for add_rule.NrO	  )r   rK	  r?   s      r   factFixedpoint.fact$  s    dD$'r   c                    [        U5      n[        U5      nUS:  at  [        US   [        5      (       a\  [        U-  " 5       nSnU H  nUR
                  X4'   US-   nM     [        U R                  R                  5       U R                  X#5      nOpUS:X  a  US   nO[        XR                  5      nU R                  US5      n[        U R                  R                  5       U R                  UR                  5       5      n[        U5      $ )zvQuery the fixedpoint engine whether formula is derivable.
You can also pass an tuple or list of recursive predicates.
r   r   F)rd   r[   r   r  r6  r   Z3_fixedpoint_query_relationsrP   rM   r#	  r  r;	  Z3_fixedpoint_queryr   r7  )r   queryr:  _declsr<  qr   s          r   rX	  Fixedpoint.query(  s     % Z7z%(K88m&FAEE	E  .dhhllndoorZAQwaE88,MM%/E#DHHLLNDOOU\\^TAa  r   c                 h   [        U5      n[        U5      nUS:  a%  [        US   [        5      (       a  [	        SS5        OgUS:X  a  US   nO[        U5      nU R                  US5      n[        U R                  R                  5       U R                  UR                  5       U5      n[        W5      $ )zdQuery the fixedpoint engine whether formula is derivable starting at the given query level.
        r   r   Funsupported)rd   r[   r   r6  r;   r  r;	  Z3_fixedpoint_query_from_lvlrP   rM   r#	  r   r7  )r   r  rX	  r:  r   s        r   query_from_lvlFixedpoint.query_from_lvl>  s     % Z7z%(H55um,QwaE
MM%/E,TXX\\^T__elln^abAa  r   c                 &   Uc  Sn[        X0R                  5      n[        U5      nU R                  [	        [        X R                  5      U5      5      n[        U R                  R                  5       U R                  UR                  5       U5        g)zupdate ruleNrY  )
rQ   rP   rd   r;	  r  r  Z3_fixedpoint_update_rulerM   r#	  r   rJ	  s        r   update_ruleFixedpoint.update_ruleN  sc    <Dxx(MM'#dHH"5t<=!$((,,.$//188:tTr   c                     [        U R                  R                  5       U R                  5      n[	        XR                  5      $ )z%Retrieve answer from last query call.)Z3_fixedpoint_get_answerrP   rM   r#	  rH  r  s     r   
get_answerFixedpoint.get_answerW  s+    $TXX\\^T__EAxx((r   c                     [        U R                  R                  5       U R                  5      n[	        XR                  5      $ )z+Retrieve a ground cex from last query call.)#Z3_fixedpoint_get_ground_sat_answerrP   rM   r#	  rH  r  s     r   get_ground_sat_answer Fixedpoint.get_ground_sat_answer\  s+    /PAxx((r   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ )z-retrieve rules along the counterexample trace)r_   #Z3_fixedpoint_get_rules_along_tracerP   rM   r#	  r   s    r   get_rules_along_trace Fixedpoint.get_rules_along_tracea  s,    <TXX\\^T__]_c_g_ghhr   c                     [        U R                  [        U R                  R                  5       U R                  5      5      nUR                  S5      $ )z2retrieve rule names along the counterexample trace;)rX   rP   (Z3_fixedpoint_get_rule_names_along_tracerM   r#	  r}  )r   r~  s     r   get_rule_names_along_trace%Fixedpoint.get_rule_names_along_tracee  s<     488%Mdhhlln^b^m^m%no{{3r   c                 t    [        U R                  R                  5       U R                  UR                  5      $ )z:Retrieve number of levels used for predicate in PDR engine)Z3_fixedpoint_get_num_levelsrP   rM   r#	  r   )r   	predicates     r   get_num_levelsFixedpoint.get_num_levelsm  s#    +DHHLLNDOOY]][[r   c                     [        U R                  R                  5       U R                  XR                  5      n[        X0R                  5      $ )zlRetrieve properties known about predicate for the level'th unfolding.
-1 is treated as the limit (infinity)
)Z3_fixedpoint_get_cover_deltarP   rM   r#	  r   rH  )r   levelrx	  r   s       r   get_cover_deltaFixedpoint.get_cover_deltaq  s5     *$((,,.$//5R_R_`Axx((r   c                     [        U R                  R                  5       U R                  XR                  UR                  5        g)z[Add property to predicate for the level'th unfolding.
-1 is treated as infinity (infinity)
N)Z3_fixedpoint_add_coverrP   rM   r#	  r   )r   r}	  rx	  propertys       r   	add_coverFixedpoint.add_coverx  s+     	 W_WcWcdr   c                     [        U5      nU H<  n[        U R                  R                  5       U R                  UR
                  5        M>     g)zRegister relation as recursiveN)rd   Z3_fixedpoint_register_relationrP   rM   r#	  r   )r   	relationsr  s      r   register_relationFixedpoint.register_relation~  s4    i(	A+DHHLLNDOOQUUS r   c                 0   [        U5      nU Vs/ s H  n[        U5      PM     nn[        U5      n[        U-  " 5       n[	        U5       H	  nX&   XV'   M     [        U R                  R                  5       U R                  UR                  XE5        gs  snf )z#Control how relation is representedN)
rd   rQ   r[   r1  r7  *Z3_fixedpoint_set_predicate_representationrP   rM   r#	  r   )r   r  representationsrH   r:  rb   r<  s          r   set_predicate_representation'Fixedpoint.set_predicate_representation  s{    #O41@AA9Q<A!rA%(DG 2488<<>4??TUTYTY[]d Bs   Bc                     [        [        U R                  R                  5       U R                  U5      U R                  5      $ )z%Parse rules and queries from a string)r_   Z3_fixedpoint_from_stringrP   rM   r#	  r!  s     r   parse_stringFixedpoint.parse_string  s/    2488<<>4??TUVX\X`X`aar   c                     [        [        U R                  R                  5       U R                  U5      U R                  5      $ )z#Parse rules and queries from a file)r_   Z3_fixedpoint_from_filerP   rM   r#	  )r   r  s     r   
parse_fileFixedpoint.parse_file  s/    0RSTVZV^V^__r   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ )z9retrieve rules that have been added to fixedpoint context)r_   Z3_fixedpoint_get_rulesrP   rM   r#	  r   s    r   	get_rulesFixedpoint.get_rules  s,    0QSWS[S[\\r   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ )z>retrieve assertions that have been added to fixedpoint context)r_   Z3_fixedpoint_get_assertionsrP   rM   r#	  r   s    r   get_assertionsFixedpoint.get_assertions  s,    5dhhllndooVX\X`X`aar   c                 "    U R                  5       $ z?Return a formatted string with all added rules and constraints.r  r   s    r   r   Fixedpoint.__repr__      zz|r   c                 z    [        U R                  R                  5       U R                  S[        S-  " 5       5      $ )yReturn a formatted string (in Lisp-like format) with all added constraints.
We say the string is in s-expression format.
r   )Z3_fixedpoint_to_stringrP   rM   r#	  r?  r   s    r   r  Fixedpoint.sexpr  s*     'txx||~tCRSG;WWr   c                 z    [        U5      u  p#[        U R                  R                  5       U R                  X25      $ )zReturn a formatted string (in Lisp-like format) with all added constraints.
We say the string is in s-expression format.
Include also queries.
)r@  r	  rP   rM   r#	  )r   queriesrb   r[   s       r   	to_stringFixedpoint.to_string  s-    
 "'*	&txx||~tRRr   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ )z2Return statistics for the last `query()`.
        )r  Z3_fixedpoint_get_statisticsrP   rM   r#	  r   s    r   r  Fixedpoint.statistics  s.     6txx||~tWY]YaYabbr   c                 ^    [        U R                  R                  5       U R                  5      $ )zNReturn a string describing why the last `query()` returned `unknown`.
        ) Z3_fixedpoint_get_reason_unknownrP   rM   r#	  r   s    r   r  Fixedpoint.reason_unknown  s     0PPr   c                 X    [        U5      nU H  nU =R                  U/-  sl        M     g)zjAdd variable or several variables.
The added variable or variables will be bound in the rules
and queries
N)rd   r  )r   r  r   s      r   declare_varFixedpoint.declare_var  s'    
 AII!I r   c                     U R                   / :X  a  U$ U(       a  [        U R                   U5      $ [        U R                   U5      $ r   )r  rj  rl  )r   r.  r  s      r   r;	  Fixedpoint.abstract  s7    99?J$))S))$))S))r   )rP   r#	  r  r  r   r  )+r   r   r   r   r   r   r   r   r^   r  r   r  r(  r  r  r  rL	  rP	  rS	  rX	  r_	  rc	  rg	  rk	  ro	  rt	  ry	  r~	  r	  r	  r	  r	  r	  r	  r	  r   r  r	  r  r  r	  r;	  r   r   r   r   r!	  r!	    s    O	 !# 5CLGiT!!!V.((!,! U)
)
i \)eTeb`]bXSc
Q
*r   r!	  c                       \ rS rSrSrS rSrg)r  i  zFinite domain sort.c                     [         R                  S-  " 5       n[        U R                  5       U R                  U5      (       a  US   $ [        S5      e)z)Return the size of the finite domain sortr   r   z*Failed to retrieve finite domain sort size)r'   c_ulonglongZ3_get_finite_domain_sort_sizer   r   r9   r  s     r   r  FiniteDomainSortRef.size  sC    !#&)$,,.$((AFFQ4KJKKr   r   N)r   r   r   r   r   r  r   r   r   r   r  r    s    Lr   r  c                     [        U [        5      (       d  [        U 5      n [        U5      n[	        [        UR                  5       X5      U5      $ )z4Create a named finite domain sort of a given size sz)r   r1  rQ   rL   r  Z3_mk_finite_domain_sortrM   )r?   r:  rP   s      r   FiniteDomainSortr	    s<    dF##
3-C7	4LcRRr   c                 "    [        U [        5      $ )zReturn True if `s` is a Z3 finite-domain sort.

>>> is_finite_domain_sort(FiniteDomainSort('S', 100))
True
>>> is_finite_domain_sort(IntSort())
False
)r   r  rG   s    r   is_finite_domain_sortr	    s     a,--r   c                   $    \ rS rSrSrS rS rSrg)rD  i  zFinite-domain expressions.c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ )z7Return the sort of the finite-domain expression `self`.)r  r  r   r   rP   r   s    r   r]  FiniteDomainRef.sort  s&    ";t||~t{{}#MtxxXXr   c                 R    [        U R                  5       U R                  5       5      $ z9Return a Z3 floating point expression as a Python string.r   r   s    r   r  FiniteDomainRef.as_string      >>r   r   N)r   r   r   r   r   r]  r  r   r   r   r   rD  rD    s    $Y?r   rD  c                 "    [        U [        5      $ )zReturn `True` if `a` is a Z3 finite-domain expression.

>>> s = FiniteDomainSort('S', 100)
>>> b = Const('b', s)
>>> is_finite_domain(b)
True
>>> is_finite_domain(Int('x'))
False
)r   rD  r%  s    r   is_finite_domainr	    s     a))r   c                   $    \ rS rSrSrS rS rSrg)rC  i
  r  c                 4    [        U R                  5       5      $ )zReturn a Z3 finite-domain numeral as a Python long (bignum) numeral.

>>> s = FiniteDomainSort('S', 100)
>>> v = FiniteDomainVal(3, s)
>>> v
3
>>> v.as_long() + 1
4
r  r   s    r   r  FiniteDomainNumRef.as_long  s     4>>#$$r   c                 R    [        U R                  5       U R                  5       5      $ )zReturn a Z3 finite-domain numeral as a Python string.

>>> s = FiniteDomainSort('S', 100)
>>> v = FiniteDomainVal(42, s)
>>> v.as_string()
'42'
r  r   s    r   r  FiniteDomainNumRef.as_string  s     %T\\^T[[]CCr   r   N)r   r   r   r   r   r  r  r   r   r   r   rC  rC  
  s    
%Dr   rC  c                     [        5       (       a  [        [        U5      S5        UR                  n[	        [        UR                  5       [        U 5      UR                  5      U5      $ )zReturn a Z3 finite-domain value. If `ctx=None`, then the global context is used.

>>> s = FiniteDomainSort('S', 256)
>>> FiniteDomainVal(255, s)
255
>>> FiniteDomainVal('100', s)
100
zExpected finite-domain sort)	r   r;   r	  rP   rC  rf  rM   rd  r   )rn   r]  rP   s      r   FiniteDomainValr	  $  sK     zz(.0MN
((CmCGGI{37GRTWXXr   c                 n    [        U 5      =(       a$    [        U R                  U R                  5       5      $ )zReturn `True` if `a` is a Z3 finite-domain value.

>>> s = FiniteDomainSort('S', 100)
>>> b = Const('b', s)
>>> is_finite_domain_value(b)
False
>>> b = FiniteDomainVal(10, s)
>>> b
10
>>> is_finite_domain_value(b)
True
)r	  r@  rP   r   r%  s    r   is_finite_domain_valuer	  3  s%     AA;quuahhj#AAr   c                   >    \ rS rSrS rS rS rS rS rS r	S r
S	rg
)OptimizeObjectiveiI  c                 (    Xl         X l        X0l        g r   )_opt_value_is_max)r   optr*   is_maxs       r   r   OptimizeObjective.__init__J  s    	r   c                     U R                   n[        [        UR                  R	                  5       UR
                  U R                  5      UR                  5      $ r   )r	  rH  Z3_optimize_get_lowerrP   rM   optimizer	  r   r	  s     r   lowerOptimizeObjective.lowerO  ;    ii1#''++-t{{[]`]d]deer   c                     U R                   n[        [        UR                  R	                  5       UR
                  U R                  5      UR                  5      $ r   )r	  rH  Z3_optimize_get_upperrP   rM   r	  r	  r	  s     r   r|   OptimizeObjective.upperS  r	  r   c                     U R                   n[        [        UR                  R	                  5       UR
                  U R                  5      UR                  5      $ r   )r	  r_   Z3_optimize_get_lower_as_vectorrP   rM   r	  r	  r	  s     r   lower_valuesOptimizeObjective.lower_valuesW  >    ii8VZVaVabdgdkdkllr   c                     U R                   n[        [        UR                  R	                  5       UR
                  U R                  5      UR                  5      $ r   )r	  r_   Z3_optimize_get_upper_as_vectorrP   rM   r	  r	  r	  s     r   upper_valuesOptimizeObjective.upper_values[  r	  r   c                 d    U R                   (       a  U R                  5       $ U R                  5       $ r   )r	  r|   r	  r   s    r   r*   OptimizeObjective.value_  s!    <<::<::<r   c                 <    U R                   < SU R                  < 3$ )N:)r	  r	  r   s    r   r   OptimizeObjective.__str__e  s    ++t||44r   )r	  r	  r	  N)r   r   r   r   r   r	  r|   r	  r	  r*   r   r   r   r   r   r	  r	  I  s)    
ffmm 5r   r	  c                 *    [         U    u  pU" U5        g r   )
_on_models)rP   fnr   s      r   _global_on_modelr	  l  s    3IRsGr   c                       \ rS rSrSrS'S jr0 4S jrS rS rS r	S	 r
S
 rS rS rS rS rS rS(S jrS rS rS rS rS rS rS rS rS rS rS rS rS rS rS r S  r!S! r"S" r#S# r$S$ r%S% r&S&r'g))Optimizeit  zaOptimize API provides methods for solving using objective functions and weighted soft constraintsNc                     [        U5      U l        Uc)  [        U R                  R                  5       5      U l        OXl        S U l        [        U R                  R                  5       U R                  5        g r   )rL   rP   Z3_mk_optimizerM   r	  _on_models_idZ3_optimize_inc_ref)r   r	  rP   s      r   r   Optimize.__init__w  sN    C=*488<<>:DM$M!DHHLLNDMM:r   c                 B    [        U R                  U R                  5      $ r   )r	  r	  rP   r   s     r   r   Optimize.__deepcopy__  s    txx00r   c                     U R                   bP  U R                  R                  5       b5  [        b.  [        U R                  R                  5       U R                   5        U R                  b  [
        U R                  	 g g r   )r	  rP   rM   Z3_optimize_dec_refr	  r	  r   s    r   r   Optimize.__del__  sX    ==$)CH[Hg>)4--. *r   c                 &    U R                  5         U $ r   rY  r   s    r   rZ  Optimize.__enter__  r\  r   c                 $    U R                  5         g r   r^  r`  s     r   rb  Optimize.__exit__  rd  r   c                     [        XU R                  5      n[        U R                  R                  5       U R                  UR
                  5        g)zbSet a configuration option.
The method `help()` return a string containing all available options.
N)r  rP   Z3_optimize_set_paramsrM   r	  r  rg  s       r   r^   Optimize.set  s2     DHH-txx||~t}}ahhGr   c                 r    [        [        U R                  R                  5       U R                  5      5        gr  )r  Z3_optimize_get_helprP   rM   r	  r   s    r   r  Optimize.help  s     "488<<>4==ABr   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ r  )r   Z3_optimize_get_param_descrsrP   rM   r	  r   s    r   r   Optimize.param_descrs  s,    :488<<>4==Y[_[c[cddr   c                    [        U5      n[        U R                  5      nU H  n[        U[        5      (       d  [        U[
        5      (       aH  U H@  n[        U R                  R                  5       U R                  UR                  5       5        MB     Mu  UR                  U5      n[        U R                  R                  5       U R                  UR                  5       5        M     g)z@Assert constraints as background axioms for the optimize solver.N)rd   r'  rP   r   r  r_   Z3_optimize_assertrM   r	  r   r_  rx  s        r   r  Optimize.assert_exprs  s    TXXC#t$$
3	(B(BA&txx||~t}}ahhjQ  ffSk"488<<>4==#**,O r   c                 "    U R                   " U6   g)zWAssert constraints as background axioms for the optimize solver. Alias for assert_expr.Nr  r  s     r   r(  Optimize.add  rA	  r   c                 (    U R                  U5        U $ r   r}  r~  s     r   r  Optimize.__iadd__  r  r   c                 |   [        U[        5      (       a  [        X R                  5      n[	        [        U[
        5      S5        [	        [        U[
        5      =(       a    [        U5      S5        [        U R                  R                  5       U R                  UR                  5       UR                  5       5        g)a  Assert constraint `a` and track it in the unsat core using the Boolean constant `p`.

If `p` is a string, it will be automatically converted into a Boolean constant.

>>> x = Int('x')
>>> p3 = Bool('p3')
>>> s = Optimize()
>>> s.assert_and_track(x > 0,  'p1')
>>> s.assert_and_track(x != 1, 'p2')
>>> s.assert_and_track(x < 0,  p3)
>>> print(s.check())
unsat
>>> c = s.unsat_core()
>>> len(c)
2
>>> Bool('p1') in c
True
>>> Bool('p2') in c
False
>>> p3 in c
True
r  N)r   rl   r  rP   r;   r  rc  Z3_optimize_assert_and_trackrM   r	  r   r  s      r   r  Optimize.assert_and_track  sx    . aQ!A:a)+HI:a)9hqk;XY$TXX\\^T]]AHHJPQPXPXPZ[r   c                   ^ ^^ [        T5      (       a  ST-  mO[        T[        5      (       a  ST-  m[        T[        5      (       d  [	        S5      eTc  Sm[        TT R                  5      mUU U4S jn[        R                  R                  S:  a-  [        U[        5      (       a  U Vs/ s H
  oT" U5      PM     sn$ U" U5      $ s  snf )a  Add soft constraint with optional weight and optional identifier.
If no weight is supplied, then the penalty for violating the soft constraint
is 1.
Soft constraints are grouped by identifiers. Soft constraints that are
added without identifiers are grouped by default.
z%dz%fz'weight should be a string or an integerrY  c                    > [        TR                  R                  5       TR                  U R	                  5       TT5      n[        TUS5      $ rw  )Z3_optimize_assert_softrP   rM   r	  r   r	  )r   r   idr   r+  s     r   asoft Optimize.add_soft.<locals>.asoft  s:    'qxxzSY[]^A$T1e44r   r   )r   r   rR  rl   r9   rQ   rP   sysversion_infor,   r   )r   rc   r+  r
  r
  r   s   ` ``  r   add_softOptimize.add_soft  s     6??F]F&&F]F&#&&GHH:Br488$	5 !!Q&:c8+D+D&)*cE!Hc**Sz +s   .C
c                     UR                  5       nUR                  U5      n[        U R                  R	                  5       U R
                  UR                  UR                  5        gr  )r]  r_  Z3_optimize_set_initial_valuerP   rM   r	  r   r  s       r   r  Optimize.set_initial_value  s@     HHJu%dhhllndmmSWWeiiXr   c           	          [        U [        U R                  R                  5       U R                  UR                  5       5      SS9$ )z#Add objective function to maximize.Tr	  )r	  Z3_optimize_maximizerP   rM   r	  r   r&  s     r   maximizeOptimize.maximize  s5      

M
 	
r   c           	          [        U [        U R                  R                  5       U R                  UR                  5       5      SS9$ )z#Add objective function to minimize.Fr)
  )r	  Z3_optimize_minimizerP   rM   r	  r   r&  s     r   minimizeOptimize.minimize  s5      

M
 	
r   c                 `    [        U R                  R                  5       U R                  5        g)zAcreate a backtracking point for added rules, facts and assertionsN)Z3_optimize_pushrP   rM   r	  r   s    r   r(  Optimize.push  s    7r   c                 `    [        U R                  R                  5       U R                  5        g)z0restore to previously created backtracking pointN)Z3_optimize_poprP   rM   r	  r   s    r   r_  Optimize.pop   s    6r   c                    [        U5      n[        U5      n[        U-  " 5       n[        U5       H  nX   R	                  5       X4'   M     [        [        U R                  R                  5       U R                  X#5      5      $ )z-Check consistency and produce optimal values.)
rd   r[   r?  r7  r   r7  Z3_optimize_checkrP   rM   r	  )r   r  r  r  r<  s        r   r  Optimize.check   sd    ,+c	}sA)n335LO /sabbr   c                 ^    [        U R                  R                  5       U R                  5      $ )zIReturn a string that describes why the last `check()` returned `unknown`.)Z3_optimize_get_reason_unknownrP   rM   r	  r   s    r   r  Optimize.reason_unknown   s    -dhhllndmmLLr   c                      [        [        U R                  R                  5       U R                  5      U R                  5      $ ! [
         a    [        S5      ef = f)z$Return a model for the last check().r  )r  Z3_optimize_get_modelrP   rM   r	  r9   r   s    r   r  Optimize.model   sL    	81$((,,.$--PRVRZRZ[[ 	8677	8r  c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ r   )r_   Z3_optimize_get_unsat_corerP   rM   r	  r   s    r   r  Optimize.unsat_core   s,    3DHHLLNDMMRTXT\T\]]r   c                 b    [        U[        5      (       d  [        S5      eUR                  5       $ Nz8Expecting objective handle returned by maximize/minimize)r   r	  r9   r	  r   objs     r   r	  Optimize.lower   (    #011XYYyy{r   c                 b    [        U[        5      (       d  [        S5      eUR                  5       $ rD
  )r   r	  r9   r|   rE
  s     r   r|   Optimize.upper#   rH
  r   c                 b    [        U[        5      (       d  [        S5      eUR                  5       $ rD
  )r   r	  r9   r	  rE
  s     r   r	  Optimize.lower_values(   +    #011XYY!!r   c                 b    [        U[        5      (       d  [        S5      eUR                  5       $ rD
  )r   r	  r9   r	  rE
  s     r   r	  Optimize.upper_values-   rM
  r   c                 b    [        U R                  R                  5       U R                  U5        g)z+Parse assertions and objectives from a fileN)Z3_optimize_from_filerP   rM   r	  r  s     r   r  Optimize.from_file2   s    dhhllndmmXFr   c                 b    [        U R                  R                  5       U R                  U5        g)z-Parse assertions and objectives from a stringN)Z3_optimize_from_stringrP   rM   r	  r!  s     r   r"  Optimize.from_string6   s    qAr   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ )z6Return an AST vector containing all added constraints.)r_   Z3_optimize_get_assertionsrP   rM   r	  r   s    r   r,  Optimize.assertions:   ,    3DHHLLNDMMRTXT\T\]]r   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ )z"returns set of objective functions)r_   Z3_optimize_get_objectivesrP   rM   r	  r   s    r   
objectivesOptimize.objectives>   rY
  r   c                 "    U R                  5       $ r	  r	  r   s    r   r   Optimize.__repr__B   r	  r   c                 ^    [        U R                  R                  5       U R                  5      $ )r	  )Z3_optimize_to_stringrP   rM   r	  r   s    r   r  Optimize.sexprF   s     %TXX\\^T]]CCr   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ )z/Return statistics for the last check`.
        )r  Z3_optimize_get_statisticsrP   rM   r	  r   s    r   r  Optimize.statisticsL   s.     4TXX\\^T]]SUYU]U]^^r   c                    [        [        5      S-   n[        U R                  5      nX4[        U'   X l        [        U R                  R                  5       U R                  UR                  [        R                  U5      [        5        g)a  Register a callback that is invoked with every incremental improvement to
objective values. The callback takes a model as argument.
The life-time of the model is limited to the callback so the
model has to be (deep) copied if it is to be used after the callback
)   N)r[   r	  r  rP   r	  Z3_optimize_register_model_ehrM   r	  r  r'   c_void_p_on_model_eh)r   on_modelr
  r   s       r   set_on_modelOptimize.set_on_modelQ   s^     _r!DHHo"
2%HHLLNDMM399foob6I<	
r   )r	  rP   r	  r  )rb  N)(r   r   r   r   r   r   r   r   rZ  rb  r^   r  r   r  r(  r  r  r#
  r  r+
  r/
  r(  r_  r  r  r  r  r	  r|   r	  r	  r  r"  r,  r\
  r   r  r  rl
  r   r   r   r   r	  r	  t  s    k; !# 1/HCe
P!\:0Y

87cM8^

"
"
GB^^D_

r   r	  c                   N    \ rS rSrSrS r0 4S jrS rS rS r	S r
S	 rS
 rSrg)ApplyResultie   zAn ApplyResult object contains the subgoals produced by a tactic when applied to a goal.
It also contains model and proof converters.
c                 x    Xl         X l        [        U R                  R                  5       U R                   5        g r   )r  rP   Z3_apply_result_inc_refrM   )r   r  rP   s      r   r   ApplyResult.__init__j   s$    <r   c                 B    [        U R                  U R                  5      $ r   )ro
  r  rP   r   s     r   r   ApplyResult.__deepcopy__o   s    4;;11r   c                     U R                   R                  5       b7  [        b/  [        U R                   R                  5       U R                  5        g g g r   )rP   rM   Z3_apply_result_dec_refr  r   s    r   r   ApplyResult.__del__r   s9    88<<>%*A*M#DHHLLNDKK@ +N%r   c                 p    [        [        U R                  R                  5       U R                  5      5      $ )ax  Return the number of subgoals in `self`.

>>> a, b = Ints('a b')
>>> g = Goal()
>>> g.add(Or(a == 0, a == 1), Or(b == 0, b == 1), a > b)
>>> t = Tactic('split-clause')
>>> r = t(g)
>>> len(r)
2
>>> t = Then(Tactic('split-clause'), Tactic('split-clause'))
>>> len(t(g))
4
>>> t = Then(Tactic('split-clause'), Tactic('split-clause'), Tactic('propagate-values'))
>>> len(t(g))
1
)r    Z3_apply_result_get_num_subgoalsrP   rM   r  r   s    r   r  ApplyResult.__len__v   s%    " 3DHHLLNDKKPQQr   c                     U[        U 5      :  a  [        e[        [        U R                  R                  5       U R                  U5      U R                  S9$ )a&  Return one of the subgoals stored in ApplyResult object `self`.

>>> a, b = Ints('a b')
>>> g = Goal()
>>> g.add(Or(a == 0, a == 1), Or(b == 0, b == 1), a > b)
>>> t = Tactic('split-clause')
>>> r = t(g)
>>> r[0]
[a == 0, Or(b == 0, b == 1), a > b]
>>> r[1]
[a == 1, Or(b == 0, b == 1), a > b]
r   )r[   r  r  Z3_apply_result_get_subgoalrP   rM   r  r  s     r   r'  ApplyResult.__getitem__   sC     #d)4TXX\\^T[[RUV\`\d\deer   c                     [        U 5      $ r   r   r   s    r   r   ApplyResult.__repr__   r   r   c                 ^    [        U R                  R                  5       U R                  5      $ )z_Return a textual representation of the s-expression representing the set of subgoals in `self`.)Z3_apply_result_to_stringrP   rM   r  r   s    r   r  ApplyResult.sexpr   s    (EEr   c                    [        U 5      nUS:X  a  [        SU R                  5      $ US:X  a  U S   R                  5       $ [	        [        [        U 5      5       Vs/ s H  o U   R                  5       PM     sn5      $ s  snf )a  Return a Z3 expression consisting of all subgoals.

>>> x = Int('x')
>>> g = Goal()
>>> g.add(x > 1)
>>> g.add(Or(x == 2, x == 3))
>>> r = Tactic('simplify')(g)
>>> r
[[Not(x <= 1), Or(x == 2, x == 3)]]
>>> r.as_expr()
And(Not(x <= 1), Or(x == 2, x == 3))
>>> r = Tactic('split-clause')(g)
>>> r
[[x > 1, x == 2], [x > 1, x == 3]]
>>> r.as_expr()
Or(And(x > 1, x == 2), And(x > 1, x == 3))
r   Fr   )r[   r  rP   r  r  r7  r  s      r   r  ApplyResult.as_expr   sn    $ Y75$((++1W7??$$%D	2BC2BQAw(2BCDDCs   A?)rP   r  N)r   r   r   r   r   r   r   r   r  r'  r   r  r  r   r   r   r   ro
  ro
  e   s9    =
 !# 2AR&f"#FEr   ro
  c                   L    \ rS rSrSrSS jr0 4S jrS rS rS r	S	 r
S
 rSrg)
Simplifieri   ziSimplifiers act as pre-processing utilities for solvers.
Build a custom simplifier and add it to a solverNc                 `   [        U5      U l        S U l        [        U[        5      (       a  Xl        GO+[        U[
        5      (       a  U Vs/ s H  n[        X25      PM     nnUS   R                  U l        [        S[        U5      5       HC  n[        U R                  R                  5       U R                  XE   R                  5      U l        ME     [        U R                  R                  5       U R                  5        g [        5       (       a  [        [        U[        5      S5         [        U R                  R                  5       [        U5      5      U l        [        U R                  R                  5       U R                  5        g s  snf ! [          a    [!        SU-  5      ef = f)Nr   r   zsimplifier name expectedzunknown simplifier '%s')rL   rP   
simplifierr   SimplifierObjr]   r
  r7  r[   Z3_simplifier_and_thenrM   Z3_simplifier_inc_refr   r;   rl   Z3_mk_simplifierr9   )r   r
  rP   rH   simpsr<  s         r   r   Simplifier.__init__   s3   C=j-00(O
D))1;<AZ'E<#Ah11DO1c%j)"8Z_ZbZmZm"n *!$((,,.$//Bzz:j#68RSJ"2488<<>3z?"S 	dhhllndoo> =  J!";j"HIIJs   F.2F F-c                 B    [        U R                  U R                  5      $ r   )r
  r
  rP   r   s     r   r   Simplifier.__deepcopy__   r*	  r   c                     U R                   bS  U R                  R                  5       b7  [        b/  [        U R                  R                  5       U R                   5        g g g g r   )r
  rP   rM   Z3_simplifier_dec_refr   s    r   r   Simplifier.__del__   r.	  r   c                     [        XU R                  5      n[        [        U R                  R	                  5       U R
                  UR                  5      U R                  5      $ )z=Return a simplifier that uses the given configuration options)r  rP   r
  Z3_simplifier_using_paramsrM   r
  r  rg  s       r   using_paramsSimplifier.using_params   sE    DHH-4TXX\\^T__VWV^V^_aeaiaijjr   c                     [        [        U R                  R                  5       UR                  U R
                  5      U R                  5      $ )zZReturn a solver that applies the simplification pre-processing specified by the simplifier)r&  Z3_solver_add_simplifierrP   rM   rO  r
  )r   rO  s     r   r(  Simplifier.add   s2    .txx||~v}}doo^`d`h`hiir   c                 r    [        [        U R                  R                  5       U R                  5      5        g)z]Display a string containing a description of the available options for the `self` simplifier.N)r  Z3_simplifier_get_helprP   rM   r
  r   s    r   r  Simplifier.help   r5	  r   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ r  )r   Z3_simplifier_get_param_descrsrP   rM   r
  r   s    r   r   Simplifier.param_descrs   r9	  r   )rP   r
  r   )r   r   r   r   r   r   r   r   r
  r(  r  r   r   r   r   r   r
  r
     s4    8?* !# 5Ck
jGir   r
  c                   V    \ rS rSrSrSS jr0 4S jrS rSS jrS r	S	 r
S
 rS rSrg)rn  i   a  Tactics transform, solver and/or simplify sets of constraints (Goal).
A Tactic can be converted into a Solver using the method solver().

Several combinators are available for creating new tactics using the built-in ones:
Then(), OrElse(), FailIf(), Repeat(), When(), Cond().
Nc                    [        U5      U l        S U l        [        U[        5      (       a  Xl        O\[        5       (       a  [        [        U[        5      S5         [        U R                  R                  5       [        U5      5      U l        [        U R                  R                  5       U R                  5        g ! [         a    [        SU-  5      ef = f)Nztactic name expectedzunknown tactic '%s')rL   rP   tacticr   	TacticObjr   r;   rl   Z3_mk_tacticrM   r9   Z3_tactic_inc_ref)r   r
  rP   s      r   r   Tactic.__init__!  s    C=fi(( Kzz:fc24JKB*488<<>3v;G 	$((,,.$++6  B!"7&"@AABs   2B? ?Cc                 B    [        U R                  U R                  5      $ r   )rn  r
  rP   r   s     r   r   Tactic.__deepcopy__!  s    dkk488,,r   c                     U R                   bS  U R                  R                  5       b7  [        b/  [        U R                  R                  5       U R                   5        g g g g r   )r
  rP   rM   Z3_tactic_dec_refr   s    r   r   Tactic.__del__!  rW  r   c                     [        [        U R                  R                  5       U R                  5      U R                  U5      $ )a.  Create a solver using the tactic `self`.

The solver supports the methods `push()` and `pop()`, but it
will always solve each `check()` from scratch.

>>> t = Then('simplify', 'nlsat')
>>> s = t.solver()
>>> x = Real('x')
>>> s.add(x**2 == 2, x > 0)
>>> s.check()
sat
>>> s.model()
[x = 1.4142135623?]
)r&  Z3_mk_solver_from_tacticrP   rM   r
  )r   rR  s     r   rO  Tactic.solver!  s.     .txx||~t{{KTXXW^__r   c                 (   [        5       (       a   [        [        U[        [        45      S5        [        U5      n[        U5      S:  d  [        U5      S:  an  [        X#U R                  5      n[        [        U R                  R                  5       U R                  UR                  UR                  5      U R                  5      $ [        [        U R                  R                  5       U R                  UR                  5      U R                  5      $ )zApply tactic `self` to the given goal or Z3 Boolean expression using the given options.

>>> x, y = Ints('x y')
>>> t = Tactic('solve-eqs')
>>> t.apply(And(x == 0, y >= x + 1))
[[y >= 1]]
z'Z3 Goal or Boolean expressions expectedr   )r   r;   r   r  r  _to_goalr[   r  rP   ro
  Z3_tactic_apply_exrM   r
  r  r  Z3_tactic_apply)r   r  r  r  r`  s        r   r  Tactic.apply(!  s     ::z$w8:cd~y>AX!2I:A1$((,,.$++tyyZ[ZbZbceiememnntxx||~t{{DIIVX\X`X`aar   c                 .    U R                   " U/UQ70 UD6$ )zApply tactic `self` to the given goal or Z3 Boolean expression using the given options.

>>> x, y = Ints('x y')
>>> t = Tactic('solve-eqs')
>>> t(And(x == 0, y >= x + 1))
[[y >= 1]]
)r  )r   r  r  r  s       r   r  Tactic.__call__9!  s     zz$77h77r   c                 r    [        [        U R                  R                  5       U R                  5      5        g)zYDisplay a string containing a description of the available options for the `self` tactic.N)r  Z3_tactic_get_helprP   rM   r
  r   s    r   r  Tactic.helpC!  r  r   c                     [        [        U R                  R                  5       U R                  5      U R                  5      $ r  )r   Z3_tactic_get_param_descrsrP   rM   r
  r   s    r   r   Tactic.param_descrsG!  r	  r   )rP   r
  r   )r   r   r   r   r   r   r   r   rO  r  r  r  r   r   r   r   r   rn  rn     s7    7 !# -;`"b"8?ar   rn  c                 |    [        U [        5      (       a&  [        U R                  S9nUR	                  U 5        U$ U $ )Nr   )r   r  r  rP   r(  )r   r  s     r   r
  r
  L!  s1    !Wr   c                 F    [        U [        5      (       a  U $ [        X5      $ r   )r   rn  )r	  rP   s     r   
_to_tacticr
  U!  s    !Va~r   c                 ,   [        X5      n [        X5      n[        5       (       a#  [        U R                  UR                  :H  S5        [	        [        U R                  R                  5       U R                  UR                  5      U R                  5      $ r.  )r
  r   r;   rP   rn  Z3_tactic_and_thenrM   r
  t1t2rP   s      r   	_and_thenr
  \!  sb    	B	B	B	Bzz266RVV#%78$RVVZZ\299biiH"&&QQr   c                 ,   [        X5      n [        X5      n[        5       (       a#  [        U R                  UR                  :H  S5        [	        [        U R                  R                  5       U R                  UR                  5      U R                  5      $ r.  )r
  r   r;   rP   rn  Z3_tactic_or_elserM   r
  r
  s      r   _or_elser
  d!  sb    	B	B	B	Bzz266RVV#%78#BFFJJL"))RYYGPPr   c                      [        5       (       a  [        [        U 5      S:  S5        UR                  SS5      n[        U 5      nU S   n[	        US-
  5       H  n[        X@US-      U5      nM     U$ )zReturn a tactic that applies the tactics in `*ts` in sequence.

>>> x, y = Ints('x y')
>>> t = AndThen(Tactic('simplify'), Tactic('solve-eqs'))
>>> t(And(x == 0, y > x + 1))
[[Not(y <= 1)]]
>>> t(And(x == 0, y > x + 1)).as_expr()
Not(y <= 1)
rx   r  rP   Nr   r   )r   r;   r[   r  r7  r
  r  ksrP   r  r   r<  s         r   AndThenr
  l!  sk     zz3r7a<!BC
&&
C
b'C
1A37^aAEC( Hr   c                      [        U 0 UD6$ )a  Return a tactic that applies the tactics in `*ts` in sequence. Shorthand for AndThen(*ts, **ks).

>>> x, y = Ints('x y')
>>> t = Then(Tactic('simplify'), Tactic('solve-eqs'))
>>> t(And(x == 0, y > x + 1))
[[Not(y <= 1)]]
>>> t(And(x == 0, y > x + 1)).as_expr()
Not(y <= 1)
)r
  )r  r
  s     r   Thenr
  !  s     B"r   c                      [        5       (       a  [        [        U 5      S:  S5        UR                  SS5      n[        U 5      nU S   n[	        US-
  5       H  n[        X@US-      U5      nM     U$ )a:  Return a tactic that applies the tactics in `*ts` until one of them succeeds (it doesn't fail).

>>> x = Int('x')
>>> t = OrElse(Tactic('split-clause'), Tactic('skip'))
>>> # Tactic split-clause fails if there is no clause in the given goal.
>>> t(x == 0)
[[x == 0]]
>>> t(Or(x == 0, x == 1))
[[x == 0], [x == 1]]
rx   r  rP   Nr   r   )r   r;   r[   r  r7  r
  r
  s         r   OrElser
  !  sk     zz3r7a<!BC
&&
C
b'C
1A37^Q1q5	3' Hr   c                     [        5       (       a  [        [        U 5      S:  S5        [        UR	                  SS5      5      nU  Vs/ s H  n[        X25      PM     n n[        U 5      n[        U-  " 5       n[        U5       H  nX   R                  XV'   M     [        [        UR                  5       XE5      U5      $ s  snf )zReturn a tactic that applies the tactics in `*ts` in parallel until one of them succeeds (it doesn't fail).

>>> x = Int('x')
>>> t = ParOr(Tactic('simplify'), Tactic('fail'))
>>> t(x + 1 == 2)
[[x == 1]]
rx   r  rP   N)r   r;   r[   rL   r  r
  r
  r7  r
  rn  Z3_tactic_par_orrM   )r  r
  rP   r	  r:  r;  r<  s          r   ParOrr
  !  s     zz3r7a<!BC
266%&
'C&(	)b*Q
bB	)	RB^E2Y5<< "3779b8#>> 
*s   B=c                 ,   [        X5      n [        X5      n[        5       (       a#  [        U R                  UR                  :H  S5        [	        [        U R                  R                  5       U R                  UR                  5      U R                  5      $ )a!  Return a tactic that applies t1 and then t2 to every subgoal produced by t1.
The subgoals are processed in parallel.

>>> x, y = Ints('x y')
>>> t = ParThen(Tactic('split-clause'), Tactic('propagate-values'))
>>> t(And(Or(x == 1, x == 2), y == x + 1))
[[x == 1, y == 2], [x == 2, y == 3]]
r/  )r
  r   r;   rP   rn  Z3_tactic_par_and_thenrM   r
  r
  s      r   ParThenr
  !  sd     
B	B	B	Bzz266RVV#%78(ryy"))LbffUUr   c                     [        XU5      $ )zAlias for ParThen(t1, t2, ctx).)r
  r
  s      r   
ParAndThenr
  !  s    23r   c                    UR                  SS5      n[        X5      n [        XU R                  5      n[	        [        U R                  R                  5       U R                  UR                  5      U R                  5      $ )zReturn a tactic that applies tactic `t` using the given configuration options.

>>> x, y = Ints('x y')
>>> t = With(Tactic('simplify'), som=True)
>>> t((x + 1)*(y + 2) == 0)
[[2*x + y + x*y == -2]]
rP   N)	r_  r
  r  rP   rn  Z3_tactic_using_paramsrM   r
  r  )r	  rb   ri  rP   r`  s        r   Withr
  !  s[     ((5$
C1AD&A(ahhI155QQr   c                     [        U S5      n [        [        U R                  R	                  5       U R
                  UR                  5      U R                  5      $ )zReturn a tactic that applies tactic `t` using the given configuration options.

>>> x, y = Ints('x y')
>>> p = ParamsRef()
>>> p.set("som", True)
>>> t = WithParams(Tactic('simplify'), p)
>>> t((x + 1)*(y + 2) == 0)
[[2*x + y + x*y == -2]]
N)r
  rn  r
  rP   rM   r
  r  )r	  r`  s     r   
WithParamsr
  !  s=     	1dA(ahhI155QQr   c                     [        X5      n [        [        U R                  R	                  5       U R
                  U5      U R                  5      $ )a  Return a tactic that keeps applying `t` until the goal is not modified anymore
or the maximum number of iterations `max` is reached.

>>> x, y = Ints('x y')
>>> c = And(Or(x == 0, x == 1), Or(y == 0, y == 1), x > y)
>>> t = Repeat(OrElse(Tactic('split-clause'), Tactic('skip')))
>>> r = t(c)
>>> for subgoal in r: print(subgoal)
[x == 0, y == 0, x > y]
[x == 0, y == 1, x > y]
[x == 1, y == 0, x > y]
[x == 1, y == 1, x > y]
>>> t = Then(t, Tactic('propagate-values'))
>>> t(c)
[[x == 1, y == 0]]
)r
  rn  Z3_tactic_repeatrP   rM   r
  )r	  maxrP   s      r   Repeatr
  !  s7    " 	1A"15599;#>FFr   c                     [        X5      n [        [        U R                  R	                  5       U R
                  U5      U R                  5      $ )zReturn a tactic that applies `t` to a given goal for `ms` milliseconds.

If `t` does not terminate in `ms` milliseconds, then it fails.
)r
  rn  Z3_tactic_try_forrP   rM   r
  )r	  msrP   s      r   TryForr
  !  s7    
 	1A#AEEIIK2>FFr   c                     [        U 5      n [        [        U R                  5       5      5       Vs/ s H  n[	        U R                  5       U5      PM     sn$ s  snf )zcReturn a list of all available tactics in Z3.

>>> l = tactics()
>>> l.count('simplify') == 1
True
)rL   r7  Z3_get_num_tacticsrM   Z3_get_tactic_namerP   r<  s     r   tacticsr
  "  sF     3-C6;<Nswwy<Y6Z[6Zswwy!,6Z[[[   $Ac                 L    [        U5      n[        UR                  5       U 5      $ )z`Return a short description for the tactic named `name`.

>>> d = tactic_description('simplify')
)rL   Z3_tactic_get_descrrM   r  s     r   tactic_descriptionr
  "  s     
 3-Cswwy$//r   c                  `   [        5       (       as  Sn [        S5        [        5        HL  nU (       a  [        S5        Sn O[        S5        Sn [        SU< S[        [	        U5      S5      < S	35        MN     [        S
5        g[        5        H  n[        U< S[	        U5      < 35        M      g)z?Display a (tabular) description of all available tactics in Z3.Tr  r  Fr  r  r  (   r  r   : N)r   r  r
  insert_line_breaksr
  )r   r	  s     r   describe_tacticsr
  "  s    ~~BCA=>f16HI[\]I^`b6cde  	jAq"4Q"789 r   c                   ^    \ rS rSrSrSS jr0 4S jrS rS rS r	S	 r
S
 rS rS rS rSrg)rm  i+"  zProbes are used to inspect a goal (aka problem) and collect information that may be used
to decide which solver and/or preprocessing step will be used.
Nc                    [        U5      U l        S U l        [        U[        5      (       a  Xl        GOF[        U[
        5      (       a+  [        U R                  R                  5       U5      U l        GO[        U5      (       a3  [        U R                  R                  5       [        U5      5      U l        O[        U[        5      (       a[  U(       a*  [        U R                  R                  5       S5      U l        O}[        U R                  R                  5       S5      U l        OS[        5       (       a  [        [        U[        5      S5         [        U R                  R                  5       U5      U l        [        U R                  R                  5       U R                  5        g ! [         a    [        SU-  5      ef = f)N      ?        zprobe name expectedzunknown probe '%s')rL   rP   r  r   ProbeObjrR  Z3_probe_constrM   r   rk   r   r;   rl   Z3_mk_prober9   Z3_probe_inc_ref)r   r  rP   s      r   r   Probe.__init__0"  s%   C=
eX&&Ju%%'>DJU^^'eEDJt$$+DHHLLNC@
+DHHLLNC@
zz:eS13HI@(?
 	4  @!"6">??@s   )F* *Gc                 B    [        U R                  U R                  5      $ r   )rm  r  rP   r   s     r   r   Probe.__deepcopy__G"  s    TZZ**r   c                     U R                   bS  U R                  R                  5       b7  [        b/  [        U R                  R                  5       U R                   5        g g g g r   )r  rP   rM   Z3_probe_dec_refr   s    r   r   Probe.__del__J"  sF    ::!dhhlln&@EUEaTXX\\^TZZ8 Fb&@!r   c           
          [        [        U R                  R                  5       U R                  [        XR                  5      R                  5      U R                  5      $ )zReturn a probe that evaluates to "true" when the value returned by `self`
is less than the value returned by `other`.

>>> p = Probe('size') < 10
>>> x = Int('x')
>>> g = Goal()
>>> g.add(x > 0)
>>> g.add(x < 10)
>>> p(g)
1.0
)rm  Z3_probe_ltrP   rM   r  	_to_prober   s     r   r  Probe.__lt__N"  >     [Yuhh=W=]=]^`d`h`hiir   c           
          [        [        U R                  R                  5       U R                  [        XR                  5      R                  5      U R                  5      $ )zReturn a probe that evaluates to "true" when the value returned by `self`
is greater than the value returned by `other`.

>>> p = Probe('size') > 10
>>> x = Int('x')
>>> g = Goal()
>>> g.add(x > 0)
>>> g.add(x < 10)
>>> p(g)
0.0
)rm  Z3_probe_gtrP   rM   r  r  r   s     r   rm  Probe.__gt__\"  r  r   c           
          [        [        U R                  R                  5       U R                  [        XR                  5      R                  5      U R                  5      $ )zReturn a probe that evaluates to "true" when the value returned by `self`
is less than or equal to the value returned by `other`.

>>> p = Probe('size') <= 2
>>> x = Int('x')
>>> g = Goal()
>>> g.add(x > 0)
>>> g.add(x < 10)
>>> p(g)
1.0
)rm  Z3_probe_lerP   rM   r  r  r   s     r   r  Probe.__le__j"  r  r   c           
          [        [        U R                  R                  5       U R                  [        XR                  5      R                  5      U R                  5      $ )zReturn a probe that evaluates to "true" when the value returned by `self`
is greater than or equal to the value returned by `other`.

>>> p = Probe('size') >= 2
>>> x = Int('x')
>>> g = Goal()
>>> g.add(x > 0)
>>> g.add(x < 10)
>>> p(g)
1.0
)rm  Z3_probe_gerP   rM   r  r  r   s     r   r  Probe.__ge__x"  r  r   c           
          [        [        U R                  R                  5       U R                  [        XR                  5      R                  5      U R                  5      $ )zReturn a probe that evaluates to "true" when the value returned by `self`
is equal to the value returned by `other`.

>>> p = Probe('size') == 2
>>> x = Int('x')
>>> g = Goal()
>>> g.add(x > 0)
>>> g.add(x < 10)
>>> p(g)
1.0
)rm  Z3_probe_eqrP   rM   r  r  r   s     r   r   Probe.__eq__"  r  r   c                     U R                  U5      n[        [        U R                  R	                  5       UR
                  5      U R                  5      $ )zReturn a probe that evaluates to "true" when the value returned by `self`
is not equal to the value returned by `other`.

>>> p = Probe('size') != 2
>>> x = Int('x')
>>> g = Goal()
>>> g.add(x > 0)
>>> g.add(x < 10)
>>> p(g)
0.0
)r   rm  r  rP   rM   r  )r   r   r`  s      r   ri  Probe.__ne__"  s8     KK\$((,,.!'':DHHEEr   c                     [        5       (       a   [        [        U[        [        45      S5        [        U5      n[        U R                  R                  5       U R                  UR                  5      $ )a2  Evaluate the probe `self` in the given goal.

>>> p = Probe('size')
>>> x = Int('x')
>>> g = Goal()
>>> g.add(x > 0)
>>> g.add(x < 10)
>>> p(g)
2.0
>>> g.add(x < 20)
>>> p(g)
3.0
>>> p = Probe('num-consts')
>>> p(g)
1.0
>>> p = Probe('is-propositional')
>>> p(g)
0.0
>>> p = Probe('is-qflia')
>>> p(g)
1.0
z&Z3 Goal or Boolean expression expected)r   r;   r   r  r  r
  Z3_probe_applyrP   rM   r  r  )r   r  s     r   r  Probe.__call__"  sK    . ::z$w8:bc~dhhllndjj$))DDr   )rP   r  r   )r   r   r   r   r   r   r   r   r  rm  r  r  r   ri  r  r   r   r   r   rm  rm  +"  sE    5. !# +9jjjjjFEr   rm  c                 "    [        U [        5      $ )zeReturn `True` if `p` is a Z3 probe.

>>> is_probe(Int('x'))
False
>>> is_probe(Probe('memory'))
True
)r   rm  )r`  s    r   r0  r0  "  s     ar   c                 <    [        U 5      (       a  U $ [        X5      $ r   )r0  rm  r`  rP   s     r   r  r  "  s    {{Q}r   c                     [        U 5      n [        [        U R                  5       5      5       Vs/ s H  n[	        U R                  5       U5      PM     sn$ s  snf )z_Return a list of all available probes in Z3.

>>> l = probes()
>>> l.count('memory') == 1
True
)rL   r7  Z3_get_num_probesrM   Z3_get_probe_namer
  s     r   probesr  "  sF     3-C5:;LSWWY;W5XY5Xcggi+5XYYYr
  c                 L    [        U5      n[        UR                  5       U 5      $ )z\Return a short description for the probe named `name`.

>>> d = probe_description('memory')
)rL   Z3_probe_get_descrrM   r  s     r   probe_descriptionr!  "  s     
 3-Ccggi..r   c                  `   [        5       (       as  Sn [        S5        [        5        HL  nU (       a  [        S5        Sn O[        S5        Sn [        SU< S[        [	        U5      S5      < S	35        MN     [        S
5        g[        5        H  n[        U< S[	        U5      < 35        M      g)z>Display a (tabular) description of all available probes in Z3.Tr  r  Fr  r  r  r
  r  r  r
  N)r   r  r  r
  r!  )r   r`  s     r   describe_probesr#  "  s    ~~BCA=>f16HIZ[\I]_a6bcd  	jAq"3A"678 r   c                 <   [        5       (       a  [        [        U5      S:  S5        [        U5      n[        US   U5      n[	        US-
  5       HH  n[        U " UR                  5       UR                  [        XS-      U5      R                  5      U5      nMJ     U$ )Nr   r	  r   )r   r;   r[   r  r7  rm  rM   r  )r  rb   rP   r  r   r<  s         r   _probe_naryr%  "  s~    zz3t9q="BC
d)C$q'3A37^!CGGIqww	$1u+s(C(I(IJCP Hr   c                 "    [        [        X5      $ r   )r%  Z3_probe_andrb   rP   s     r   r  r  #  s    |T//r   c                 "    [        [        X5      $ r   )r%  Z3_probe_orr(  s     r   r  r  #  s    {D..r   c                     [        X5      n [        [        U R                  R	                  5       U R
                  5      U R                  5      $ )a  Return a tactic that fails if the probe `p` evaluates to true.
Otherwise, it returns the input goal unmodified.

In the following example, the tactic applies 'simplify' if and only if there are
more than 2 constraints in the goal.

>>> t = OrElse(FailIf(Probe('size') > 2), Tactic('simplify'))
>>> x, y = Ints('x y')
>>> g = Goal()
>>> g.add(x > 0)
>>> g.add(y > 0)
>>> t(g)
[[x > 0, y > 0]]
>>> g.add(x == y + 1)
>>> t(g)
[[Not(x <= 0), Not(y <= 0), x == 1 + y]]
)r  rn  Z3_tactic_fail_ifrP   rM   r  r  s     r   FailIfr-  #  s5    $ 	!A#AEEIIK9155AAr   c                     [        X5      n [        X5      n[        [        UR                  R                  5       U R                  UR                  5      UR                  5      $ )a]  Return a tactic that applies tactic `t` only if probe `p` evaluates to true.
Otherwise, it returns the input goal unmodified.

>>> t = When(Probe('size') > 2, Tactic('simplify'))
>>> x, y = Ints('x y')
>>> g = Goal()
>>> g.add(x > 0)
>>> g.add(y > 0)
>>> t(g)
[[x > 0, y > 0]]
>>> g.add(x == y + 1)
>>> t(g)
[[Not(x <= 0), Not(y <= 0), x == 1 + y]]
)r  r
  rn  Z3_tactic_whenrP   rM   r  r
  )r`  r	  rP   s      r   Whenr0  !#  sD     	!A1A.aggqxx@!%%HHr   c                     [        X5      n [        X5      n[        X#5      n[        [        UR                  R                  5       U R                  UR                  UR                  5      UR                  5      $ )zReturn a tactic that applies tactic `t1` to a goal if probe `p` evaluates to true, and `t2` otherwise.

>>> t = Cond(Probe('is-qfnra'), Tactic('qfnra'), Tactic('smt'))
)r  r
  rn  Z3_tactic_condrP   rM   r  r
  )r`  r
  r
  rP   s       r   ro  ro  5#  sT    
 	!A	B	B	B	B.qww		299MrvvVVr   c                    [        5       (       a  [        [        U 5      S5        [        U5      S:  d  [        U5      S:  a]  [	        XU R
                  5      n[        [        U R                  5       U R                  5       UR                  5      U R
                  5      $ [        [        U R                  5       U R                  5       5      U R
                  5      $ )a  Simplify the expression `a` using the given options.

This function has many options. Use `help_simplify` to obtain the complete list.

>>> x = Int('x')
>>> y = Int('y')
>>> simplify(x + 1 + y + x + 1)
2 + 2*x + y
>>> simplify((x + 1)*(y + 1), som=True)
1 + x + y + x*y
>>> simplify(Distinct(x, y, 1), blast_distinct=True)
And(Not(x == y), Not(x == 1), Not(y == 1))
>>> simplify(And(x == 0, y == 1), elim_and=True)
Not(Or(Not(x == 0), Not(y == 1)))
r[  r   )r   r;   r\  r[   r  rP   rH  Z3_simplify_exr   r   r  Z3_simplify)r   r  r  r`  s       r   ri  ri  F#  s      zz71:78
9~S]Q.	QUU3N199;
AHHMquuUUK		QXXZ@!%%HHr   c                  X    [        [        [        5       R                  5       5      5        g)zMReturn a string describing all options available for Z3 `simplify` procedure.N)r  Z3_simplify_get_helpr   rM   r   r   r   help_simplifyr8  _#  s    	
xz~~/
01r   c                  h    [        [        [        5       R                  5       5      [        5       5      $ )zEReturn the set of parameter descriptions for Z3 `simplify` procedure.)r   Z3_simplify_get_param_descrsr   rM   r   r   r   simplify_param_descrsr;  d#  s     6xz~~7GH(*UUr   c                    [        U[        5      (       a9  [        U5      n[        U[        5      (       a  [	        S U 5       5      (       a  Un[        5       (       a  [        [        U 5      S5        [        [	        U Vs/ s H=  n[        U[        5      =(       a#    [        US   5      =(       a    [        US   5      PM?     sn5      S5        [        [	        U Vs/ s H5  o3S   R                  5       R                  US   R                  5       5      PM7     sn5      S5        [        U5      n[        U-  " 5       n[        U-  " 5       n[        U5       H1  nX   S   R                  5       XW'   X   S   R                  5       Xg'   M3     [        [        U R                   R#                  5       U R                  5       XEU5      U R                   5      $ s  snf s  snf )a>  Apply substitution m on t, m is a list of pairs of the form (from, to).
Every occurrence in t of from is replaced with to.

>>> x = Int('x')
>>> y = Int('y')
>>> substitute(x + 1, (x, y + 1))
y + 1 + 1
>>> f = Function('f', IntSort(), IntSort())
>>> substitute(f(x) + f(y), (f(x), IntVal(1)), (f(y), IntVal(1)))
1 + 1
c              3   B   #    U  H  n[        U[        5      v   M     g 7fr   r   r\   .0r`  s     r   	<genexpr>substitute.<locals>.<genexpr>w#       'Ib
1e(<(<b   r[  r   r   z3Z3 invalid substitution, expression pairs expected.z;Z3 invalid substitution, mismatching "from" and "to" sorts.)r   r\   rd   r]   r
  r   r;   r\  r]  r   r[   r?  r7  r   rH  Z3_substituterP   rM   r	  rH  m1r`  r  _from_tor<  s           r   
substituterJ  i#  so    !Uq\b$C'Ib'I$I$IAzz71:78STUSTaAu%I'!A$-IGAaDMISTUVA	C 	a8a1!		,a89I	K a&C3YME9-C3Z47>>#a!  aeeiik188:s3OQRQVQVWW V 9s   AG<Gc           
         [        5       (       aD  [        [        U 5      S5        [        [        U Vs/ s H  n[        U5      PM     sn5      S5        [	        U5      n[
        U-  " 5       n[        U5       H  nX   R                  5       XE'   M     [        [        U R                  R                  5       U R                  5       X45      U R                  5      $ s  snf )a  Substitute the free variables in t with the expression in m.

>>> v0 = Var(0, IntSort())
>>> v1 = Var(1, IntSort())
>>> x  = Int('x')
>>> f  = Function('f', IntSort(), IntSort(), IntSort())
>>> # replace v0 with x+1 and v1 with x
>>> substitute_vars(f(v0, v1), x + 1, x)
f(x + 1, x)
r[  z6Z3 invalid substitution, list of expressions expected.)r   r;   r\  r
  r[   r?  r7  r   rH  Z3_substitute_varsrP   rM   )r	  rH  r>   r  rI  r<  s         r   substitute_varsrM  #  s     zz71:783A.Aq
A./1ij
a&C9-C3Z *15599;
CMquuUU /s   Cc                 
   [        U[        5      (       a9  [        U5      n[        U[        5      (       a  [	        S U 5       5      (       a  Un[        5       (       as  [        [        U 5      S5        [        [	        U Vs/ s H=  n[        U[        5      =(       a#    [        US   5      =(       a    [        US   5      PM?     sn5      S5        [        U5      n[        U-  " 5       n[        U-  " 5       n[        U5       H1  nX   S   R                  5       XW'   X   S   R                  5       Xg'   M3     [        [!        U R"                  R%                  5       U R                  5       XEU5      U R"                  5      $ s  snf )a  Apply substitution m on t, m is a list of pairs of a function and expression (from, to)
Every occurrence in to of the function from is replaced with the expression to.
The expression to can have free variables, that refer to the arguments of from.
For examples, see 
c              3   B   #    U  H  n[        U[        5      v   M     g 7fr   r>  r?  s     r   rA  "substitute_funs.<locals>.<genexpr>#  rC  rD  r[  r   r   z1Z3 invalid substitution, function pairs expected.)r   r\   rd   r]   r
  r   r;   r\  r  r[   r6  r?  r7  r8  r   rH  Z3_substitute_funsrP   rM   rF  s           r   substitute_funsrR  #  s5    !Uq\b$C'Ib'I$I$IAzz71:783_`a_`Z[
1e,Uad1CUPQRSPTU_`ab  eX  	Y
a&C^E9-C3Z47'')a!  *15599;
CPSTVWV[V[\\ bs   AF c                  *   [        U 5      n [        U 5      S:X  a  g[        U 5      nUc  [        S U S5      $ [	        X5      n [        U S   5      (       a  [        S U S5      $ [        U 5      u  p#[        [        UR                  5       X25      U5      $ )zCreate the sum of the Z3 expressions.

>>> a, b, c = Ints('a b c')
>>> Sum(a, b, c)
a + b + c
>>> Sum([a, b, c])
a + b + c
>>> A = IntVector('a', 5)
>>> Sum(A)
a__0 + a__1 + a__2 + a__3 + a__4
r   c                 
    X-   $ r   r   r(  s     r   <lambda>Sum.<locals>.<lambda>#      AEr   c                 
    X-   $ r   r   r(  s     r   rU  rV  #  rW  r   )
rd   r[   r2  rZ  r^  r  r@  r7  r  rM   rt  s       r   SumrY  #       T?D
4yA~
 
&C
{)433T'DT!W~~)433!$'		#'')R7==r   c                  *   [        U 5      n [        U 5      S:X  a  g[        U 5      nUc  [        S U S5      $ [	        X5      n [        U S   5      (       a  [        S U S5      $ [        U 5      u  p#[        [        UR                  5       X25      U5      $ )zCreate the product of the Z3 expressions.

>>> a, b, c = Ints('a b c')
>>> Product(a, b, c)
a*b*c
>>> Product([a, b, c])
a*b*c
>>> A = IntVector('a', 5)
>>> Product(A)
a__0*a__1*a__2*a__3*a__4
r   r   c                 
    X-  $ r   r   r(  s     r   rU  Product.<locals>.<lambda>#  rW  r   c                 
    X-  $ r   r   r(  s     r   rU  r]  #  rW  r   )
rd   r[   r2  rZ  r^  r  r@  r7  r  rM   rt  s       r   Productr_  #  rZ  r   c                 "    [        U S:  X * 5      $ )z5Create the absolute value of an arithmetic expressionr   )rq  r  s    r   Absra  #  s    cAgsD!!r   c                  B   [        U 5      n [        5       (       a  [        [        U 5      S:  S5        [	        U 5      n[        5       (       a  [        USLS5        [        U SS U5      nU S   n[        U5      u  pE[        [        UR                  5       XTU5      U5      $ )zhCreate an at-most Pseudo-Boolean k constraint.

>>> a, b, c = Bools('a b c')
>>> f = AtMost(a, b, c, 2)
r   $Non empty list of arguments expectedNrs  r  )
rd   r   r;   r[   r2  r^  r@  r  Z3_mk_atmostrM   rb   rP   args1r   r;  r:  s         r   AtMostrg  #  s     T?Dzz3t9q="HI
 
&Czz3d?$[\d3Bi-ERAe$IE<	2a8#>>r   c                  B   [        U 5      n [        5       (       a  [        [        U 5      S:  S5        [	        U 5      n[        5       (       a  [        USLS5        [        U SS U5      nU S   n[        U5      u  pE[        [        UR                  5       XTU5      U5      $ )zjCreate an at-least Pseudo-Boolean k constraint.

>>> a, b, c = Bools('a b c')
>>> f = AtLeast(a, b, c, 2)
r   rc  Nrs  r  )
rd   r   r;   r[   r2  r^  r@  r  Z3_mk_atleastrM   re  s         r   AtLeastrj  #  s     T?Dzz3t9q="HI
 
&Czz3d?$[\d3Bi-ERAe$IE=Bq93??r   c                 T    U u  p[        U5      (       d  [        U5      (       a  X!4$ U $ r   )r   )rc   r   r&  s      r   _reorder_pb_argrl  $  s&    DA1::'!**tJr   c                 d   [        U 5      n [        U 5      S:X  a1  [        U5      S[        S-  " 5       [        R
                  S-  " 5       4$ U  Vs/ s H  n[        U5      PM     n n[        U 6 u  p[        5       (       a  [        [        U 5      S:  S5        [        U 5      n[        5       (       a  [        US LS5        [        X5      n [        U 5      u  pV[        R
                  [        U5      -  " 5       n[        [        U5      5       H  n[        X8   S5        X8   Xx'   M     XFXWU 4$ s  snf )Nr   rc  rs  coefficient)rg   r[   rL   r?  r'   r=   rl  zipr   r;   r2  r^  r@  r7  r@   )	rb   r1  rc   coeffsrP   r;  r:  _coeffsr<  s	            r   _pb_args_coeffsrr  $  s   d#D
4yA~$a#'v||a7G6JJJ,01DSOC DD1:LDzz3t9q="HI
 
&Czz3d?$[\T'Dd#IE||c&k),G3v;	=9Y
   ED(( 2s   D-c           	          [        US5        [        U 5      u  p#pEn [        [        UR	                  5       X4XQ5      U5      $ )ztCreate a Pseudo-Boolean inequality k constraint.

>>> a, b, c = Bools('a b c')
>>> f = PbLe(((a,1),(b,3),(c,2)), 3)
r   )r@   rr  r  
Z3_mk_pblerM   rb   r   rP   r:  r;  rq  s         r   PbLerv  +$  ;     As#$3D$9!CUT:cggiG?EEr   c           	          [        US5        [        U 5      u  p#pEn [        [        UR	                  5       X4XQ5      U5      $ )ztCreate a Pseudo-Boolean inequality k constraint.

>>> a, b, c = Bools('a b c')
>>> f = PbGe(((a,1),(b,3),(c,2)), 3)
r   )r@   rr  r  
Z3_mk_pbgerM   ru  s         r   PbGerz  6$  rw  r   c           	          [        US5        [        U 5      u  p#pEn [        [        UR	                  5       X4XQ5      U5      $ )zrCreate a Pseudo-Boolean equality k constraint.

>>> a, b, c = Bools('a b c')
>>> f = PbEq(((a,1),(b,3),(c,2)), 3)
r   )r@   rr  r  
Z3_mk_pbeqrM   ru  s         r   PbEqr}  A$  rw  r   c                     UR                  SS5      n[        5       nUR                  " S0 UD6  UR                  " U 6   U(       a  [	        U5        UR                  5       nU[        :X  a  [	        S5        gU[        :X  a&  [	        S5         [	        UR                  5       5        g[	        UR                  5       5        g! [         a     gf = f)zSolve the constraints `*args`.

This is a simple function for creating demonstrations. It creates a solver,
configure it using the options in `keywords`, adds the constraints
in `args`, and invokes check.

>>> a = Int('a')
>>> solve(a > 0, a < 2)
[a = 1]
showFno solutionfailed to solveNr   
r_  r&  r^   r(  r  r  rC  rD  r  r9   rb   r  r  rH   r   s        r   solver  L$  s     <<&DAEEHEE4La		AEzm	
g 	!'') 	aggi  		s   C   
CCc                    UR                  SS5      n[        5       (       a  [        [        U [        5      S5        U R
                  " S	0 UD6  U R                  " U6   U(       a  [        S5        [        U 5        U R                  5       nU[        :X  a  [        S5        gU[        :X  a&  [        S5         [        U R                  5       5        gU(       a  [        S5        [        U R                  5       5        g! [         a     gf = f)
a  Solve the constraints `*args` using solver `s`.

This is a simple function for creating demonstrations. It is similar to `solve`,
but it uses the given solver `s`.
It configures solver `s` using the options in `keywords`, adds the constraints
in `args`, and invokes check.
r  FSolver object expectedzProblem:r  r  Nz	Solution:r   r_  r   r;   r   r&  r^   r(  r  r  rC  rD  r  r9   rH   rb   r  r  r   s        r   solve_usingr  j$  s     <<&Dzz:a(*BCEEHEE4Lja		AEzm	
g 	!'') +aggi  		   6C< <
D	D	c                    [        5       (       a  [        [        U 5      S5        [        5       nUR                  " S0 UD6  UR                  [        U 5      5        U(       a  [        U5        UR                  5       nU[        :X  a  [        S5        gU[        :X  a%  [        S5        [        UR                  5       5        g[        S5        [        UR                  5       5        g)zTry to prove the given claim.

This is a simple function for creating demonstrations.  It tries to prove
`claim` by showing the negation is unsatisfiable.

>>> p, q = Bools('p q')
>>> prove(Not(And(p, q)) == Or(Not(p), Not(q)))
proved
Z3 Boolean expression expectedprovedzfailed to provecounterexampleNr   r   r;   r  r&  r^   r(  r  r  r  rC  rD  r  claimr  r  rH   r   s        r   prover  $  s     zz75>#CDAEEHEE#e*a		AEzh	
g aggiaggir   c                     UR                  SS5      n[        5       nUR                  " S0 UD6  UR                  " U 6   U(       a  [	        S5        [	        U5        UR                  5       nU[        :X  a  [	        S5        gU[        :X  a&  [	        S5         [	        UR                  5       5        gU(       a  [	        S5        [	        UR                  5       5        g! [         a     gf = f)	z5Version of function `solve` that renders HTML output.r  F<b>Problem:</b><b>no solution</b><b>failed to solve</b>N<b>Solution:</b>r   r  r  s        r   _solve_htmlr  $  s    <<&DAEEHEE4L a		AEz"#	
g&'	!'') $%aggi  		s   C 
C*)C*c                    UR                  SS5      n[        5       (       a  [        [        U [        5      S5        U R
                  " S	0 UD6  U R                  " U6   U(       a  [        S5        [        U 5        U R                  5       nU[        :X  a  [        S5        gU[        :X  a&  [        S5         [        U R                  5       5        gU(       a  [        S5        [        U R                  5       5        g! [         a     gf = f)
z4Version of function `solve_using` that renders HTML.r  Fr  r  r  r  Nr  r   r  r  s        r   _solve_using_htmlr  $  s    <<&Dzz:a(*BCEEHEE4L a		AEz"#	
g&'	!'') $%aggi  		r  c                    [        5       (       a  [        [        U 5      S5        [        5       nUR                  " S0 UD6  UR                  [        U 5      5        U(       a  [        U5        UR                  5       nU[        :X  a  [        S5        gU[        :X  a%  [        S5        [        UR                  5       5        g[        S5        [        UR                  5       5        g)z.Version of function `prove` that renders HTML.r  z<b>proved</b>z<b>failed to prove</b>z<b>counterexample</b>Nr   r  r  s        r   _prove_htmlr  $  s    zz75>#CDAEEHEE#e*a		AEzo	
g&'aggi%&aggir   c                 2   [        U 5      n[        U-  " 5       n[        U-  " 5       nSnU  He  nX   n[        5       (       a/  [	        [        U[        5      S5        [	        [        U5      S5        [        Xa5      X5'   UR                  XE'   US-   nMg     X#U4$ )Nr   r  r  r   )
r[   r1  rx  r   r;   r   rl   ru  rQ   r   )r  rP   r:  _names_sortsr<  r   r   s           r   _dict2sarrayr  $  s    	UBrk_FRi]F	AH::z!S)+<=wqz#56a%	EE	E  vr   c                    [        U 5      n[        U-  " 5       n[        U-  " 5       nSnU  H  nX   n[        5       (       aA  [	        [        U[        5      S5        [	        [        U5      =(       d    [        U5      S5        [        Xa5      X5'   [        U5      (       a  UR                  5       R                  XE'   OUR                  XE'   US-   nM     X#U4$ )Nr   r  z#Z3 declaration or constant expectedr   )r[   r1  r6  r   r;   r   rl   r  rc  rQ   r  r   )r  rP   r:  r  rY	  r<  r   r   s           r   _dict2darrayr  $  s    	UBrk_FmF	AH::z!S)+<=|A5(1+7\]a%	A;;FIFIE  vr   c                   6    \ rS rSrS	S jrS rS rS rS rSr	g)
ParserContexti%  Nc                     [        U5      U l        [        U R                  R                  5       5      U l        [        U R                  R                  5       U R                  5        g r   )rL   rP   Z3_mk_parser_contextrM   pctxZ3_parser_context_inc_ref)r   rP   s     r   r   ParserContext.__init__%  s;    C=(8	!$((,,.$))<r   c                     U R                   R                  5       bL  U R                  b>  [        b6  [        U R                   R                  5       U R                  5        S U l        g g g g r   )rP   rM   r  Z3_parser_context_dec_refr   s    r   r   ParserContext.__del__%  sM    88<<>%$))*?D]Di%dhhllndii@DI Ej*?%r   c                 ~    [        U R                  R                  5       U R                  UR	                  5       5        g r   )Z3_parser_context_add_sortrP   rM   r  r   )r   r]  s     r   add_sortParserContext.add_sort%  "    "488<<>499dkkmLr   c                 ~    [        U R                  R                  5       U R                  UR	                  5       5        g r   )Z3_parser_context_add_declrP   rM   r  r   )r   r  s     r   add_declParserContext.add_decl%  r  r   c                     [        [        U R                  R                  5       U R                  U5      U R                  5      $ r   )r_   Z3_parser_context_from_stringrP   rM   r  r!  s     r   r"  ParserContext.from_string%  s/    6txx||~tyyRSTVZV^V^__r   )rP   r  r   )
r   r   r   r   r   r   r  r  r"  r   r   r   r   r  r  %  s    =

MM`r   r  c                     [        U5      n[        X5      u  pEn[        X#5      u  pxn	[        [	        UR                  5       XXVXxU	5      U5      $ )a0  Parse a string in SMT 2.0 format using the given sorts and decls.

The arguments sorts and decls are Python dictionaries used to initialize
the symbol table used for the SMT 2.0 parser.

>>> parse_smt2_string('(declare-const x Int) (assert (> x 0)) (assert (< x 10))')
[x > 0, x < 10]
>>> x, y = Ints('x y')
>>> f = Function('f', IntSort(), IntSort())
>>> parse_smt2_string('(assert (> (+ foo (g bar)) 0))', decls={ 'foo' : x, 'bar' : y, 'g' : f})
[x + f(y) > 0]
>>> parse_smt2_string('(declare-const a U) (assert (> a 0))', sorts={ 'U' : IntSort() })
[a > 0]
)rL   r  r  r_   Z3_parse_smtlib2_stringrM   )
rH   r  r  rP   sszsnamesssortsdszdnamesddeclss
             r   parse_smt2_stringr   %  sO     3-C&u2C&u2C,SWWYPS]cdfijjr   c                     [        U5      n[        X5      u  pEn[        X#5      u  pxn	[        [	        UR                  5       XXVXxU	5      U5      $ )zrParse a file in SMT 2.0 format using the given sorts and decls.

This function is similar to parse_smt2_string().
)rL   r  r  r_   Z3_parse_smtlib2_filerM   )
r  r  r  rP   r  r  r  r  r  r  s
             r   parse_smt2_filer  5%  sN    
 3-C&u2C&u2C*3779afc[abdghhr      5   c                     [         [        :X  a  [        U 5      $ [         [        :X  a  [	        U 5      $ [         [
        :X  a  [        U 5      $ [         [        :X  a  [        U 5      $ [         [        :X  a  [        U 5      $ g)z+Retrieves the global default rounding mode.N)_dflt_rounding_modeZ3_OP_FPA_RM_TOWARD_ZERORTZZ3_OP_FPA_RM_TOWARD_NEGATIVERTNZ3_OP_FPA_RM_TOWARD_POSITIVERTP!Z3_OP_FPA_RM_NEAREST_TIES_TO_EVENRNE!Z3_OP_FPA_RM_NEAREST_TIES_TO_AWAYRNAr   s    r   get_default_rounding_moder  M%  sd     663x	 <	<3x	 <	<3x	 A	A3x	 A	A3x 
Br   c                 x    [        U 5      (       a  U R                  5       qg [        [        [        ;   S5        U qg )Nzillegal rounding mode)is_fprm_valuerU  r  r;   _ROUNDING_MODES)rmrP   s     r   set_default_rounding_moder  e%  s0    R ggi&/9;RS r   c                 ,    [        [        [        U 5      $ r   )FPSort_dflt_fpsort_ebits_dflt_fpsort_sbitsr   s    r   get_default_fp_sortr  n%  s    $&8#>>r   c                     U q Uqg r   )r  r  ebitssbitsrP   s      r   set_default_fp_sortr  r%  s     r   c                     [        U 5      $ r   )r  r   s    r   _dflt_rmr  y%  s    $S))r   c                     [        U 5      $ r   )r  r   s    r   	_dflt_fpsr  }%  s    s##r   c           	      .   S nU  HA  n[        U5      (       d  M  Uc  UR                  5       nM*  X#R                  5       :X  a  M?  S n  O   / n[        [        U 5      5       H  nX   n[	        U[
        5      =(       a)    UR                  S5      =(       a    UR                  S5      nU(       d+  [        U5      (       d  [	        U[        [        45      (       a  UR                  [        US X!5      5        M  UR                  U5        M     [        XA5      $ )Nz2**(r  )is_fpr]  r7  r[   r   rl   containsendswithr   rR  rk   r  FPValr^  )r\  rP   first_fp_sortr   r   r<  is_reprs          r   _coerce_fp_expr_listr  %  s    M88$ !&&(* !%  	A3u:HQ$OF);O

3gajjJq5$-$@$@HHU1dM78HHQK  Q$$r   c                   *    \ rS rSrSrS rS rS rSrg)r  i%  zFloating-point sort.c                 \    [        [        U R                  5       U R                  5      5      $ )zRetrieves the number of bits reserved for the exponent in the FloatingPoint sort `self`.
>>> b = FPSort(8, 24)
>>> b.ebits()
8
)r   Z3_fpa_get_ebitsr   r   r   s    r   r  FPSortRef.ebits%  !     #DLLNDHH=>>r   c                 \    [        [        U R                  5       U R                  5      5      $ )zRetrieves the number of bits reserved for the significand in the FloatingPoint sort `self`.
>>> b = FPSort(8, 24)
>>> b.sbits()
24
)r   Z3_fpa_get_sbitsr   r   r   s    r   r  FPSortRef.sbits%  r  r   c                     [        U5      (       a4  [        5       (       a#  [        U R                  UR                  :H  S5        U$ [	        USX R                  5      $ )zTry to cast `val` as a floating-point expression.
>>> b = FPSort(8, 24)
>>> b.cast(1.0)
1
>>> b.cast(1.0).sexpr()
'(fp #b0 #x7f #b00000000000000000000000)'
r/  N)r\  r   r;   rP   r  r^  s     r   r_  FPSortRef.cast%  sD     3<<zz488sww.0BCJdD((33r   r   N)	r   r   r   r   r   r  r  r_  r   r   r   r   r  r  %  s    ??4r   r  c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ z"Floating-point 16-bit (half) sort.)rL   r  Z3_mk_fpa_sort_16rM   r   s    r   Float16r  %  $    
3-C&swwy1377r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ r  )rL   r  Z3_mk_fpa_sort_halfrM   r   s    r   	FloatHalfr   %  s$    
3-C(3S99r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ z$Floating-point 32-bit (single) sort.)rL   r  Z3_mk_fpa_sort_32rM   r   s    r   Float32r  %  r  r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ r  )rL   r  Z3_mk_fpa_sort_singlerM   r   s    r   FloatSingler  %  $    
3-C*37795s;;r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ z$Floating-point 64-bit (double) sort.)rL   r  Z3_mk_fpa_sort_64rM   r   s    r   Float64r  %  r  r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ r
  )rL   r  Z3_mk_fpa_sort_doublerM   r   s    r   FloatDoubler  %  r  r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ z(Floating-point 128-bit (quadruple) sort.)rL   r  Z3_mk_fpa_sort_128rM   r   s    r   Float128r  %  s$    
3-C'	2C88r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ r  )rL   r  Z3_mk_fpa_sort_quadruplerM   r   s    r   FloatQuadrupler  %  s$    
3-C-cggi8#>>r   c                       \ rS rSrSrSrg)r  i%  z#"Floating-point rounding mode sort.r   Nr   r   r   r   r   r   r   r   r   r  r  %  s    -r   r  c                 "    [        U [        5      $ )ztReturn True if `s` is a Z3 floating-point sort.

>>> is_fp_sort(FPSort(8, 24))
True
>>> is_fp_sort(IntSort())
False
)r   r  rG   s    r   
is_fp_sortr  %  s     a##r   c                 "    [        U [        5      $ )zReturn True if `s` is a Z3 floating-point rounding mode sort.

>>> is_fprm_sort(FPSort(8, 24))
False
>>> is_fprm_sort(RNE().sort())
True
)r   r  rG   s    r   is_fprm_sortr  %  s     a%%r   c                       \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rS rS rS rS rS rS rS rS rS rS rS rS rSrg)rB  i&  zFloating-point expressions.c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ )zReturn the sort of the floating-point expression `self`.

>>> x = FP('1.0', FPSort(8, 24))
>>> x.sort()
FPSort(8, 24)
>>> x.sort() == FPSort(8, 24)
True
)r  r  r   r   rP   r   s    r   r]  
FPRef.sort&  r  r   c                 >    U R                  5       R                  5       $ )zRetrieves the number of bits reserved for the exponent in the FloatingPoint expression `self`.
>>> b = FPSort(8, 24)
>>> b.ebits()
8
)r]  r  r   s    r   r  FPRef.ebits&       yy{  ""r   c                 >    U R                  5       R                  5       $ )zRetrieves the number of bits reserved for the exponent in the FloatingPoint expression `self`.
>>> b = FPSort(8, 24)
>>> b.sbits()
24
)r]  r  r   s    r   r  FPRef.sbits!&  r"  r   c                 R    [        U R                  5       U R                  5       5      $ r	  r   r   s    r   r  FPRef.as_string)&  r	  r   c                 .    [        XU R                  5      $ r   )fpLEQrP   r   s     r   r  FPRef.__le__-&      T$((++r   c                 .    [        XU R                  5      $ r   )fpLTrP   r   s     r   r  FPRef.__lt__0&      D**r   c                 .    [        XU R                  5      $ r   )fpGEQrP   r   s     r   r  FPRef.__ge__3&  r*  r   c                 .    [        XU R                  5      $ r   )fpGTrP   r   s     r   rm  FPRef.__gt__6&  r.  r   c                 r    [        X/U R                  5      u  p#[        [        5       X#U R                  5      $ )zCreate the Z3 expression `self + other`.

>>> x = FP('x', FPSort(8, 24))
>>> y = FP('y', FPSort(8, 24))
>>> x + y
x + y
>>> (x + y).sort()
FPSort(8, 24)
r  rP   fpAddr  r  s       r   r  FPRef.__add__9&  -     &tmTXX>XZtxx00r   c                 r    [        X/U R                  5      u  p#[        [        5       X#U R                  5      $ )zdCreate the Z3 expression `other + self`.

>>> x = FP('x', FPSort(8, 24))
>>> 10 + x
1.25*(2**3) + x
r6  r  s       r   r  FPRef.__radd__F&  -     &umTXX>XZtxx00r   c                 r    [        X/U R                  5      u  p#[        [        5       X#U R                  5      $ )zCreate the Z3 expression `self - other`.

>>> x = FP('x', FPSort(8, 24))
>>> y = FP('y', FPSort(8, 24))
>>> x - y
x - y
>>> (x - y).sort()
FPSort(8, 24)
r  rP   fpSubr  r  s       r   r  FPRef.__sub__P&  r9  r   c                 r    [        X/U R                  5      u  p#[        [        5       X#U R                  5      $ )zdCreate the Z3 expression `other - self`.

>>> x = FP('x', FPSort(8, 24))
>>> 10 - x
1.25*(2**3) - x
r>  r  s       r   r  FPRef.__rsub__]&  r<  r   c                 r    [        X/U R                  5      u  p#[        [        5       X#U R                  5      $ )zCreate the Z3 expression `self * other`.

>>> x = FP('x', FPSort(8, 24))
>>> y = FP('y', FPSort(8, 24))
>>> x * y
x * y
>>> (x * y).sort()
FPSort(8, 24)
>>> 10 * y
1.25*(2**3) * y
r  rP   fpMulr  r  s       r   r  FPRef.__mul__g&  -     &tmTXX>XZtxx00r   c                 r    [        X/U R                  5      u  p#[        [        5       X#U R                  5      $ )zCreate the Z3 expression `other * self`.

>>> x = FP('x', FPSort(8, 24))
>>> y = FP('y', FPSort(8, 24))
>>> x * y
x * y
>>> x * 10
x * 1.25*(2**3)
rD  r  s       r   r  FPRef.__rmul__v&  -     &umTXX>XZtxx00r   c                     U $ )z!Create the Z3 expression `+self`.r   r   s    r   r  FPRef.__pos__&  s    r   c                     [        U 5      $ )zHCreate the Z3 expression `-self`.

>>> x = FP('x', Float32())
>>> -x
-x
)fpNegr   s    r   r  FPRef.__neg__&  s     T{r   c                 r    [        X/U R                  5      u  p#[        [        5       X#U R                  5      $ )zCreate the Z3 expression `self / other`.

>>> x = FP('x', FPSort(8, 24))
>>> y = FP('y', FPSort(8, 24))
>>> x / y
x / y
>>> (x / y).sort()
FPSort(8, 24)
>>> 10 / y
1.25*(2**3) / y
r  rP   fpDivr  r  s       r   r  FPRef.__div__&  rG  r   c                 r    [        X/U R                  5      u  p#[        [        5       X#U R                  5      $ )zCreate the Z3 expression `other / self`.

>>> x = FP('x', FPSort(8, 24))
>>> y = FP('y', FPSort(8, 24))
>>> x / y
x / y
>>> x / 10
x / 1.25*(2**3)
rQ  r  s       r   r  FPRef.__rdiv__&  rJ  r   c                 $    U R                  U5      $ )z1Create the Z3 expression division `self / other`.r  r   s     r   r  FPRef.__truediv__&  r  r   c                 $    U R                  U5      $ )z1Create the Z3 expression division `other / self`.r  r   s     r   r  FPRef.__rtruediv__&  r  r   c                     [        X5      $ )z,Create the Z3 expression mod `self % other`.fpRemr   s     r   r  FPRef.__mod__&  s    T!!r   c                     [        X5      $ )z,Create the Z3 expression mod `other % self`.r[  r   s     r   r  FPRef.__rmod__&  s    U!!r   r   N)r   r   r   r   r   r]  r  r  r  r  r  r  rm  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r   r   r   rB  rB  &  st    %	O##?,+,+11111111#$""r   rB  c                       \ rS rSrSrS rSrg)rE  i&  z(Floating-point rounding mode expressionsc                 R    [        U R                  5       U R                  5       5      $ r	  r   r   s    r   r  FPRMRef.as_string&  r	  r   r   N)r   r   r   r   r   r  r   r   r   r   rE  rE  &  s
    2?r   rE  c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ r   rL   rE  $Z3_mk_fpa_round_nearest_ties_to_evenrM   r   s    r   RoundNearestTiesToEvenrf  &  $    
3-C7	BCHHr   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ r   rd  r   s    r   r  r  &  rg  r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ r   rL   rE  $Z3_mk_fpa_round_nearest_ties_to_awayrM   r   s    r   RoundNearestTiesToAwayrl  &  rg  r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ r   rj  r   s    r   r  r  &  rg  r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ r   rL   rE  Z3_mk_fpa_round_toward_positiverM   r   s    r   RoundTowardPositiverq  &  $    
3-C23779=sCCr   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ r   ro  r   s    r   r  r  &  rr  r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ r   rL   rE  Z3_mk_fpa_round_toward_negativerM   r   s    r   RoundTowardNegativerw  &  rr  r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ r   ru  r   s    r   r  r  &  rr  r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ r   rL   rE  Z3_mk_fpa_round_toward_zerorM   r   s    r   RoundTowardZeror|  &  $    
3-C.swwy93??r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ r   rz  r   s    r   r  r  &  r}  r   c                 "    [        U [        5      $ )zReturn `True` if `a` is a Z3 floating-point rounding mode expression.

>>> rm = RNE()
>>> is_fprm(rm)
True
>>> rm = 1.0
>>> is_fprm(rm)
False
)r   rE  r%  s    r   is_fprmr  &  rv  r   c                 f    [        U 5      =(       a     [        U R                  U R                  5      $ )zHReturn `True` if `a` is a Z3 floating-point rounding mode numeral value.)r  r@  rP   r   r%  s    r   r  r  '  s     1:3+aeeQUU33r   c                       \ rS rSrSrS r S r S r S r S r	 SS jr
 SS	 jr SS
 jr S r S r S r S r S r S r S r S rS rSrg)rA  i'  zThe sign of the numeral.

>>> x = FPVal(+1.0, FPSort(8, 24))
>>> x.sign()
False
>>> x = FPVal(-1.0, FPSort(8, 24))
>>> x.sign()
True
c                     [         R                  5       n[        U R                  R	                  5       U R                  5       [        U5      5      nUSL a  [        S5      eUR                  S:g  $ )NFz'error retrieving the sign of a numeral.r   )	r'   r=   Z3_fpa_get_numeral_signrP   rM   r   byrefr9   r*   )r   r  nsigns      r   signFPNumRef.sign'  sQ    ||'uSzRE>GHHyyA~r   c                     [        [        U R                  R                  5       U R	                  5       5      U R                  5      $ r   )r;  Z3_fpa_get_numeral_sign_bvrP   rM   r   r   s    r   
sign_as_bvFPNumRef.sign_as_bv"'  s.    6txx||~t{{}UW[W_W_``r   c                 f    [        U R                  R                  5       U R                  5       5      $ r   )%Z3_fpa_get_numeral_significand_stringrP   rM   r   r   s    r   significandFPNumRef.significand,'  s    4TXX\\^T[[]SSr   c                     [         R                  S-  " 5       n[        U R                  R	                  5       U R                  5       U5      (       d  [        S5      eUS   $ )Nr   z.error retrieving the significand of a numeral.r   )r'   r	  %Z3_fpa_get_numeral_significand_uint64rP   rM   r   r9   )r   r   s     r   significand_as_longFPNumRef.significand_as_long6'  sJ    !!A%(4TXX\\^T[[]TWXXNOO1vr   c                     [        [        U R                  R                  5       U R	                  5       5      U R                  5      $ r   )r;  !Z3_fpa_get_numeral_significand_bvrP   rM   r   r   s    r   significand_as_bvFPNumRef.significand_as_bvA'  s.    =dhhllndkkm\^b^f^fggr   c                 h    [        U R                  R                  5       U R                  5       U5      $ r   )"Z3_fpa_get_numeral_exponent_stringrP   rM   r   r   biaseds     r   exponentFPNumRef.exponentK'  s"    1$((,,.$++-QWXXr   c                     [         R                  S-  " 5       n[        U R                  R	                  5       U R                  5       X!5      (       d  [        S5      eUS   $ )Nr   z+error retrieving the exponent of a numeral.r   )r'   
c_longlong!Z3_fpa_get_numeral_exponent_int64rP   rM   r   r9   )r   r  r   s      r   exponent_as_longFPNumRef.exponent_as_longU'  sJ      1$'0PS\\KLL1vr   c                     [        [        U R                  R                  5       U R	                  5       U5      U R                  5      $ r   )r;  Z3_fpa_get_numeral_exponent_bvrP   rM   r   r  s     r   exponent_as_bvFPNumRef.exponent_as_bv`'  s1    :488<<>4;;=Z`acgckckllr   c                 f    [        U R                  R                  5       U R                  5       5      $ r   )Z3_fpa_is_numeral_nanrP   rM   r   r   s    r   isNaNFPNumRef.isNaNe'      $TXX\\^T[[]CCr   c                 f    [        U R                  R                  5       U R                  5       5      $ r   )Z3_fpa_is_numeral_infrP   rM   r   r   s    r   isInfFPNumRef.isInfj'  r  r   c                 f    [        U R                  R                  5       U R                  5       5      $ r   )Z3_fpa_is_numeral_zerorP   rM   r   r   s    r   isZeroFPNumRef.isZeroo'  s    %dhhllndkkmDDr   c                 f    [        U R                  R                  5       U R                  5       5      $ r   )Z3_fpa_is_numeral_normalrP   rM   r   r   s    r   isNormalFPNumRef.isNormalt'  s    'FFr   c                 f    [        U R                  R                  5       U R                  5       5      $ r   )Z3_fpa_is_numeral_subnormalrP   rM   r   r   s    r   isSubnormalFPNumRef.isSubnormaly'  s    *488<<>4;;=IIr   c                 f    [        U R                  R                  5       U R                  5       5      $ r   )Z3_fpa_is_numeral_positiverP   rM   r   r   s    r   
isPositiveFPNumRef.isPositive~'      )$((,,.$++-HHr   c                 f    [        U R                  R                  5       U R                  5       5      $ r   )Z3_fpa_is_numeral_negativerP   rM   r   r   s    r   
isNegativeFPNumRef.isNegative'  r  r   c                     [        U R                  R                  5       U R                  5       5      nSU< SU R	                  5       < S3$ )NzFPVal(r  r  )r  rP   rM   r   r]  r!  s     r   r  FPNumRef.as_string'  s/    !$((,,.$++-@#$diik23r   c                     [        [        U 5      5      nUR                  5       n[        U[        5      (       d  g SS KnUR                  SSS9nUR                  SU5      S   $ )Nr      big)	byteorderz>d)ri  
fpToIEEEBVr"  r   r   structto_bytesunpack)r   r  binaryr  	bytes_reps        r   r"  FPNumRef.py_value'  sW    j&'&#&&OOAO7	}}T9-a00r   r   Nr  )r   r   r   r   r   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r"  r   r   r   r   rA  rA  '  s    
aT
hY
m 2D 7D ;E 3G 6J 5I 5I41r   rA  c                 "    [        U [        5      $ )zReturn `True` if `a` is a Z3 floating-point expression.

>>> b = FP('b', FPSort(8, 24))
>>> is_fp(b)
True
>>> is_fp(b + 1.0)
True
>>> is_fp(Int('x'))
False
)r   rB  r%  s    r   r  r  '  s     ar   c                 f    [        U 5      =(       a     [        U R                  U R                  5      $ )zReturn `True` if `a` is a Z3 floating-point numeral value.

>>> b = FP('b', FPSort(8, 24))
>>> is_fp_value(b)
False
>>> b = FPVal(1.0, FPSort(8, 24))
>>> b
1
>>> is_fp_value(b)
True
)r  r@  rP   r   r%  s    r   is_fp_valuer  '  s"     81AEE15511r   c                 `    [        U5      n[        [        UR                  5       X5      U5      $ )zReturn a Z3 floating-point sort of the given sizes. If `ctx=None`, then the global context is used.

>>> Single = FPSort(8, 24)
>>> Double = FPSort(11, 53)
>>> Single
FPSort(8, 24)
>>> x = Const('x', Single)
>>> eq(x, FP('x', FPSort(8, 24)))
True
)rL   r  Z3_mk_fpa_sortrM   r  s      r   r  r  '  s'     3-C^CGGIu<cBBr   c                 >   [        U [        5      (       a  [        R                  " U 5      (       a  SnGOZU S:X  a  [        R                  " SU 5      nUS:  a  ggU [        S5      :X  a  SnGO"U [        S5      :X  a  S	nGOU R                  5       nUS
   nUS   n[        U5      S-   [        U5      -   nUS-   [        U5      -   nO[        U [        5      (       a  U (       a  SnOSnO[        U 5      (       a  [        U 5      nO[        U [        5      (       a[  U R                  S5      nUS:X  a  U nO\U S   S:X  a+  U S
U n[        [        XS-   S 5      [        U5      -   5      nO([        SS5        O[        5       (       a  [        SS5        US
:X  a  W$ WS-   U-   $ )NNaNr
  r
  -0.0+0.0+inf+oo-inf-oor   r   /r`  z1.00.0z*(2**r  r     Fz1String does not have floating-point numeral form.z>Python value cannot be used to create floating-point numerals.)r   rR  mathisnancopysignas_integer_ratiorl   rd  rk   r   findr   r;   r   )	rn   expr   soner   r  denrvsinxs	            r   _to_float_strr  '  sp   #u::c??CCZ==c*DczE&M!CE&M!C$$&AA$CA$Cc(S.3s8+C)k#..C	C		CC	#h	C		hhw"9CW^a*Cc#Agb/*SX56CuQR	5Z[
ax
Sy3r   c                     [        [        U [        5      S5        [        [	        U R                  5       U R                  5      U R                  5      $ )zCreate a Z3 floating-point NaN term.

>>> s = FPSort(8, 24)
>>> set_fpa_pretty(True)
>>> fpNaN(s)
NaN
>>> pb = get_fpa_pretty()
>>> set_fpa_pretty(False)
>>> fpNaN(s)
fpNaN(FPSort(8, 24))
>>> set_fpa_pretty(pb)
rL  )r;   r   r  rA  Z3_mk_fpa_nanr   r   rP   rG   s    r   fpNaNr  '  s7     z!Y'9M!))+quu5quu==r   c                     [        [        U [        5      S5        [        [	        U R                  5       U R                  S5      U R                  5      $ )zCreate a Z3 floating-point +oo term.

>>> s = FPSort(8, 24)
>>> pb = get_fpa_pretty()
>>> set_fpa_pretty(True)
>>> fpPlusInfinity(s)
+oo
>>> set_fpa_pretty(False)
>>> fpPlusInfinity(s)
fpPlusInfinity(FPSort(8, 24))
>>> set_fpa_pretty(pb)
rL  Fr;   r   r  rA  Z3_mk_fpa_infr   r   rP   rG   s    r   fpPlusInfinityr  (  s9     z!Y'9M!))+quue<aeeDDr   c                     [        [        U [        5      S5        [        [	        U R                  5       U R                  S5      U R                  5      $ )z$Create a Z3 floating-point -oo term.rL  Tr  rG   s    r   fpMinusInfinityr  (  s7    z!Y'9M!))+quud;QUUCCr   c                     [        [        U [        5      S5        [        [        U[        5      S5        [	        [        U R                  5       U R                  U5      U R                  5      $ )z+Create a Z3 floating-point +oo or -oo term.rL  expected Boolean flag)	r;   r   r  rk   rA  r  r   r   rP   rH   negatives     r   
fpInfinityr  (  sI    z!Y'9z(D)+BCM!))+quuh?GGr   c                     [        [        U [        5      S5        [        [	        U R                  5       U R                  S5      U R                  5      $ )z%Create a Z3 floating-point +0.0 term.rL  Fr;   r   r  rA  Z3_mk_fpa_zeror   r   rP   rG   s    r   
fpPlusZeror  $(  s7    z!Y'9N199;u=quuEEr   c                     [        [        U [        5      S5        [        [	        U R                  5       U R                  S5      U R                  5      $ )z%Create a Z3 floating-point -0.0 term.rL  Tr  rG   s    r   fpMinusZeror  *(  s7    z!Y'9N199;t<aeeDDr   c                     [        [        U [        5      S5        [        [        U[        5      S5        [	        [        U R                  5       U R                  U5      U R                  5      $ )z-Create a Z3 floating-point +0.0 or -0.0 term.rL  r  )	r;   r   r  rk   rA  r  r   r   rP   r  s     r   fpZeror  0(  sI    z!Y'9z(D)+BCN199;x@!%%HHr   c                    [        U5      n[        U5      (       a  UnSnOUc  [        U5      n[        [        U5      S5        Uc  Sn[	        U 5      nUS:X  d  US:X  a  [        U5      $ US:X  a  [        U5      $ US:X  d  US:X  a  [        U5      $ US	:X  d  US
:X  d  US:X  a  [        U5      $ US:X  d  US:X  d  US:X  a  [        U5      $ [        [        UR                  5       XBR                  5      U5      $ )a  Return a floating-point value of value `val` and sort `fps`.
If `ctx=None`, then the global context is used.

>>> v = FPVal(20.0, FPSort(8, 24))
>>> v
1.25*(2**4)
>>> print("0x%.8x" % v.exponent_as_long(False))
0x00000004
>>> v = FPVal(2.25, FPSort(8, 24))
>>> v
1.125*(2**1)
>>> v = FPVal(-2.25, FPSort(8, 24))
>>> v
-1.125*(2**1)
>>> FPVal(-0.0, FPSort(8, 24))
-0.0
>>> FPVal(0.0, FPSort(8, 24))
+0.0
>>> FPVal(+0.0, FPSort(8, 24))
+0.0
NrL  r   r  nanr  r  r  r  r  z+Infr  r  z-Inf)rL   r  r  r;   r  r  r  r  r  r  rA  rf  rM   r   )r  r  fpsrP   rn   s        r   r  r  7(  s    , 3-C#	nz#0
{

C
e|se|Sz	3	#	#-c""	#-s##cggigg>DDr   c           	          [        U[        5      (       a  Uc  UR                  nO[        U5      n[	        [        UR                  5       [        X5      UR                  5      U5      $ )a%  Return a floating-point constant named `name`.
`fpsort` is the floating-point sort.
If `ctx=None`, then the global context is used.

>>> x  = FP('x', FPSort(8, 24))
>>> is_fp(x)
True
>>> x.ebits()
8
>>> x.sort()
FPSort(8, 24)
>>> word = FPSort(8, 24)
>>> x2 = FP('x', word)
>>> eq(x, x2)
True
)	r   r  rP   rL   rB  ry  rM   rQ   r   )r?   fpsortrP   s      r   FPr	  e(  sL    " &)$$jjsmSWWY	$(<fjjI3OOr   c                     [        U5      n[        U [        5      (       a  U R                  S5      n U  Vs/ s H  n[	        X1U5      PM     sn$ s  snf )zReturn an array of floating-point constants.

>>> x, y, z = FPs('x y z', FPSort(8, 24))
>>> x.sort()
FPSort(8, 24)
>>> x.sbits()
24
>>> x.ebits()
8
>>> fpMul(RNE(), fpAdd(RNE(), x, y), z)
(x + y) * z
r|  )rL   r   rl   r}  r	  )r~  r  rP   r?   s       r   FPsr  }(  sG     3-C%C .34edBtS!e444r"  c                     [        U5      n[        U /U5      u  n [        [        UR	                  5       U R                  5       5      U5      $ )a"  Create a Z3 floating-point absolute value expression.

>>> s = FPSort(8, 24)
>>> rm = RNE()
>>> x = FPVal(1.0, s)
>>> fpAbs(x)
fpAbs(1)
>>> y = FPVal(-20.0, s)
>>> y
-1.25*(2**4)
>>> fpAbs(y)
fpAbs(-1.25*(2**4))
>>> fpAbs(-1.25*(2**4))
fpAbs(-1.25*(2**4))
>>> fpAbs(x).sort()
FPSort(8, 24)
)rL   r  rB  Z3_mk_fpa_absrM   r   r  s     r   fpAbsr  (  s=    $ 3-C
sC
(CQswwy!((*5s;;r   c                     [        U5      n[        U /U5      u  n [        [        UR	                  5       U R                  5       5      U5      $ )zCreate a Z3 floating-point addition expression.

>>> s = FPSort(8, 24)
>>> rm = RNE()
>>> x = FP('x', s)
>>> fpNeg(x)
-x
>>> fpNeg(x).sort()
FPSort(8, 24)
)rL   r  rB  Z3_mk_fpa_negrM   r   r  s     r   rN  rN  (  s=     3-C
sC
(CQswwy!((*5s;;r   c                 $   [        U5      n[        U/U5      u  n[        5       (       a*  [        [	        U5      S5        [        [        U5      S5        [        U " UR                  5       UR                  5       UR                  5       5      U5      $ )NCFirst argument must be a Z3 floating-point rounding mode expression6Second argument must be a Z3 floating-point expression	rL   r  r   r;   r  r  rB  rM   r   )r  r  r   rP   s       r   _mk_fp_unaryr  (  sh    
3-C
sC
(CQzz72; ef58UV3779biik188:6<<r   c                     [        U5      n[        U/U5      u  n[        5       (       a  [        [	        U5      S5        [        U " UR                  5       UR                  5       5      U5      $ )N5First argument must be a Z3 floating-point expressionrL   r  r   r;   r  r  rM   r   )r  r   rP   s      r   _mk_fp_unary_predr  (  sQ    
3-C
sC
(CQzz58TU1SWWY
+S11r   c           	      f   [        U5      n[        X#/U5      u  p#[        5       (       a<  [        [	        U5      S5        [        [        U5      =(       d    [        U5      S5        [        U " UR                  5       UR                  5       UR                  5       UR                  5       5      U5      $ )Nr  z?Second or third argument must be a Z3 floating-point expressionr  )r  r  r   r&  rP   s        r   
_mk_fp_binr  (  sy    
3-C!1&#.FQzz72; ef58'uQx)jk3779biik188:qxxzBCHHr   c                    [        U5      n[        X/U5      u  p[        5       (       a'  [        [	        U5      =(       d    [	        U5      S5        [        U " UR                  5       UR                  5       UR                  5       5      U5      $ Nz?First or second argument must be a Z3 floating-point expression)rL   r  r   r;   r  rB  rM   r   r  r   r&  rP   s       r   _mk_fp_bin_normr  (  sb    
3-C!1&#.FQzz58'uQx)jk3779ahhj!((*5s;;r   c                    [        U5      n[        X/U5      u  p[        5       (       a'  [        [	        U5      =(       d    [	        U5      S5        [        U " UR                  5       UR                  5       UR                  5       5      U5      $ r  r  r  s       r   _mk_fp_bin_predr!  (  sb    
3-C!1&#.FQzz58'uQx)jk1SWWY
AHHJ7==r   c           
         [        U5      n[        X#U/U5      u  p#n[        5       (       aN  [        [	        U5      S5        [        [        U5      =(       d    [        U5      =(       d    [        U5      S5        [        U " UR                  5       UR                  5       UR                  5       UR                  5       UR                  5       5      U5      $ )Nr  zGSecond, third or fourth argument must be a Z3 floating-point expressionr  )r  r  r   r&  rq   rP   s         r   _mk_fp_ternr#  (  s    
3-C$aAY4IQ1zz72; ef58 uQx 5,Y	[3779biik188:qxxz188:NPSTTr   c                 $    [        [        XX#5      $ )a  Create a Z3 floating-point addition expression.

>>> s = FPSort(8, 24)
>>> rm = RNE()
>>> x = FP('x', s)
>>> y = FP('y', s)
>>> fpAdd(rm, x, y)
x + y
>>> fpAdd(RTZ(), x, y) # default rounding mode is RTZ
fpAdd(RTZ(), x, y)
>>> fpAdd(rm, x, y).sort()
FPSort(8, 24)
)r  Z3_mk_fpa_addr  r   r&  rP   s       r   r7  r7  (  s     mRA33r   c                 $    [        [        XX#5      $ )zCreate a Z3 floating-point subtraction expression.

>>> s = FPSort(8, 24)
>>> rm = RNE()
>>> x = FP('x', s)
>>> y = FP('y', s)
>>> fpSub(rm, x, y)
x - y
>>> fpSub(rm, x, y).sort()
FPSort(8, 24)
)r  Z3_mk_fpa_subr&  s       r   r?  r?  (       mRA33r   c                 $    [        [        XX#5      $ )zCreate a Z3 floating-point multiplication expression.

>>> s = FPSort(8, 24)
>>> rm = RNE()
>>> x = FP('x', s)
>>> y = FP('y', s)
>>> fpMul(rm, x, y)
x * y
>>> fpMul(rm, x, y).sort()
FPSort(8, 24)
)r  Z3_mk_fpa_mulr&  s       r   rE  rE  )  r)  r   c                 $    [        [        XX#5      $ )zCreate a Z3 floating-point division expression.

>>> s = FPSort(8, 24)
>>> rm = RNE()
>>> x = FP('x', s)
>>> y = FP('y', s)
>>> fpDiv(rm, x, y)
x / y
>>> fpDiv(rm, x, y).sort()
FPSort(8, 24)
)r  Z3_mk_fpa_divr&  s       r   rR  rR  )  r)  r   c                 $    [        [        XU5      $ )zCreate a Z3 floating-point remainder expression.

>>> s = FPSort(8, 24)
>>> x = FP('x', s)
>>> y = FP('y', s)
>>> fpRem(x, y)
fpRem(x, y)
>>> fpRem(x, y).sort()
FPSort(8, 24)
)r  Z3_mk_fpa_remrj  s      r   r\  r\  ))  s     =!44r   c                 $    [        [        XU5      $ )zCreate a Z3 floating-point minimum expression.

>>> s = FPSort(8, 24)
>>> rm = RNE()
>>> x = FP('x', s)
>>> y = FP('y', s)
>>> fpMin(x, y)
fpMin(x, y)
>>> fpMin(x, y).sort()
FPSort(8, 24)
)r  Z3_mk_fpa_minrj  s      r   fpMinr2  7)       =!44r   c                 $    [        [        XU5      $ )zCreate a Z3 floating-point maximum expression.

>>> s = FPSort(8, 24)
>>> rm = RNE()
>>> x = FP('x', s)
>>> y = FP('y', s)
>>> fpMax(x, y)
fpMax(x, y)
>>> fpMax(x, y).sort()
FPSort(8, 24)
)r  Z3_mk_fpa_maxrj  s      r   fpMaxr6  F)  r3  r   c                 &    [        [        XX#U5      $ )z>Create a Z3 floating-point fused multiply-add expression.
    )r#  Z3_mk_fpa_fma)r  r   r&  rq   rP   s        r   fpFMAr9  U)  s     }bQ377r   c                 $    [        [        XU5      $ )z7Create a Z3 floating-point square root expression.
    )r  Z3_mk_fpa_sqrtr  r   rP   s      r   fpSqrtr=  [)  s     s33r   c                 $    [        [        XU5      $ )z;Create a Z3 floating-point roundToIntegral expression.
    )r  Z3_mk_fpa_round_to_integralr<  s      r   fpRoundToIntegralr@  a)  s     3RC@@r   c                 "    [        [        X5      $ )zCreate a Z3 floating-point isNaN expression.

>>> s = FPSort(8, 24)
>>> x = FP('x', s)
>>> y = FP('y', s)
>>> fpIsNaN(x)
fpIsNaN(x)
)r  Z3_mk_fpa_is_nanr  s     r   fpIsNaNrC  g)  s     -q66r   c                 "    [        [        X5      $ )zvCreate a Z3 floating-point isInfinite expression.

>>> s = FPSort(8, 24)
>>> x = FP('x', s)
>>> fpIsInf(x)
fpIsInf(x)
)r  Z3_mk_fpa_is_infiniter  s     r   fpIsInfrF  s)  s     2A;;r   c                 "    [        [        X5      $ )z2Create a Z3 floating-point isZero expression.
    )r  Z3_mk_fpa_is_zeror  s     r   fpIsZerorI  ~)  s     .77r   c                 "    [        [        X5      $ )z4Create a Z3 floating-point isNormal expression.
    )r  Z3_mk_fpa_is_normalr  s     r   
fpIsNormalrL  )  s     0!99r   c                 "    [        [        X5      $ )z7Create a Z3 floating-point isSubnormal expression.
    )r  Z3_mk_fpa_is_subnormalr  s     r   fpIsSubnormalrO  )  s     3Q<<r   c                 "    [        [        X5      $ )z6Create a Z3 floating-point isNegative expression.
    )r  Z3_mk_fpa_is_negativer  s     r   fpIsNegativerR  )       2A;;r   c                 "    [        [        X5      $ )z6Create a Z3 floating-point isPositive expression.
    )r  Z3_mk_fpa_is_positiver  s     r   fpIsPositiverV  )  rS  r   c                 r    [        5       (       a(  [        [        U 5      =(       d    [        U5      S5        g g r  )r   r;   r  r(  s     r   _check_fp_argsrX  )  s&    zz58'uQx)jk r   c                 $    [        [        XU5      $ )zCreate the Z3 floating-point expression `other < self`.

>>> x, y = FPs('x y', FPSort(8, 24))
>>> fpLT(x, y)
x < y
>>> (x < y).sexpr()
'(fp.lt x y)'
)r!  Z3_mk_fpa_ltrj  s      r   r,  r,  )       <s33r   c                 $    [        [        XU5      $ )zCreate the Z3 floating-point expression `other <= self`.

>>> x, y = FPs('x y', FPSort(8, 24))
>>> fpLEQ(x, y)
x <= y
>>> (x <= y).sexpr()
'(fp.leq x y)'
)r!  Z3_mk_fpa_leqrj  s      r   r(  r(  )       =!44r   c                 $    [        [        XU5      $ )zCreate the Z3 floating-point expression `other > self`.

>>> x, y = FPs('x y', FPSort(8, 24))
>>> fpGT(x, y)
x > y
>>> (x > y).sexpr()
'(fp.gt x y)'
)r!  Z3_mk_fpa_gtrj  s      r   r3  r3  )  r[  r   c                 $    [        [        XU5      $ )zCreate the Z3 floating-point expression `other >= self`.

>>> x, y = FPs('x y', FPSort(8, 24))
>>> fpGEQ(x, y)
x >= y
>>> (x >= y).sexpr()
'(fp.geq x y)'
)r!  Z3_mk_fpa_geqrj  s      r   r0  r0  )  r^  r   c                 $    [        [        XU5      $ )zCreate the Z3 floating-point expression `fpEQ(other, self)`.

>>> x, y = FPs('x y', FPSort(8, 24))
>>> fpEQ(x, y)
fpEQ(x, y)
>>> fpEQ(x, y).sexpr()
'(fp.eq x y)'
)r!  Z3_mk_fpa_eqrj  s      r   fpEQre  )  r[  r   c                 ,    [        [        XU5      5      $ )zCreate the Z3 floating-point expression `Not(fpEQ(other, self))`.

>>> x, y = FPs('x y', FPSort(8, 24))
>>> fpNEQ(x, y)
Not(fpEQ(x, y))
>>> (x != y).sexpr()
'(distinct x y)'
)r  re  rj  s      r   fpNEQrg  )  s     tA#r   c                    [        [        U 5      =(       a    [        U5      =(       a    [        U5      S5        [        U R                  5       R                  5       S:H  S5        [	        U5      n[        X0R
                  s=:H  =(       a&    UR
                  s=:H  =(       a    UR
                  :H  Os  S5        [        [        UR                  5       U R                  UR                  UR                  5      U5      $ )a  Create the Z3 floating-point value `fpFP(sgn, sig, exp)` from the three bit-vectors sgn, sig, and exp.

>>> s = FPSort(8, 24)
>>> x = fpFP(BitVecVal(1, 1), BitVecVal(2**7-1, 8), BitVecVal(2**22, 23))
>>> print(x)
fpFP(1, 127, 4194304)
>>> xv = FPVal(-1.5, s)
>>> print(xv)
-1.5
>>> slvr = Solver()
>>> slvr.add(fpEQ(x, xv))
>>> slvr.check()
sat
>>> xv = FPVal(+1.5, s)
>>> print(xv)
1.5
>>> slvr = Solver()
>>> slvr.add(fpEQ(x, xv))
>>> slvr.check()
unsat
rL  r   rK  )
r;   r  r]  r  rL   rP   rB  Z3_mk_fpa_fprM   r   )sgnr  r  rP   s       r   fpFPrk  )  s    , uSz7eCj7U3ZIsxxz A%7
3-Csgg3333CGG35GHcggi#''377CSIIr   c                    [        U5      n[        U 5      (       aI  [        U5      (       a9  [        [	        UR                  5       U R                  UR                  5      U5      $ [        U 5      (       ad  [        U5      (       aT  [        U5      (       aD  [        [        UR                  5       U R                  UR                  UR                  5      U5      $ [        U 5      (       ad  [        U5      (       aT  [        U5      (       aD  [        [        UR                  5       U R                  UR                  UR                  5      U5      $ [        U 5      (       ad  [        U5      (       aT  [        U5      (       aD  [        [        UR                  5       U R                  UR                  UR                  5      U5      $ [        S5      e)ai  Create a Z3 floating-point conversion expression from other term sorts
to floating-point.

From a bit-vector term in IEEE 754-2008 format:
>>> x = FPVal(1.0, Float32())
>>> x_bv = fpToIEEEBV(x)
>>> simplify(fpToFP(x_bv, Float32()))
1

From a floating-point term with different precision:
>>> x = FPVal(1.0, Float32())
>>> x_db = fpToFP(RNE(), x, Float64())
>>> x_db.sort()
FPSort(11, 53)

From a real term:
>>> x_r = RealVal(1.5)
>>> simplify(fpToFP(RNE(), x_r, Float32()))
1.5

From a signed bit-vector term:
>>> x_signed = BitVecVal(-5, BitVecSort(32))
>>> simplify(fpToFP(RNE(), x_signed, Float32()))
-1.25*(2**2)
zKUnsupported combination of arguments for conversion to floating-point term.)rL   r  r  rB  Z3_mk_fpa_to_fp_bvrM   r   r  r  Z3_mk_fpa_to_fp_floatrr  Z3_mk_fpa_to_fp_realZ3_mk_fpa_to_fp_signedr9   )a1a2a3rP   s       r   fpToFPrt  *  s   4 3-CRyyZ^^'	266266BCHH	rz"~~*3779bffbffbffMsSS	B)#'')RVVRVVRVVLcRR	rz"~~+CGGIrvvrvvrvvNPSTTghhr   c                     [        [        U 5      S5        [        [        U5      S5        [        U5      n[	        [        UR                  5       U R                  UR                  5      U5      $ )zCreate a Z3 floating-point conversion expression that represents the
conversion from a bit-vector term to a floating-point term.

>>> x_bv = BitVecVal(0x3F800000, 32)
>>> x_fp = fpBVToFP(x_bv, Float32())
>>> x_fp
fpToFP(1065353216)
>>> simplify(x_fp)
1
r  z1Second argument must be a Z3 floating-point sort.)r;   r  r  rL   rB  rm  rM   r   )r   r]  rP   s      r   fpBVToFPrv  -*  sQ     uQxLMz$!TU
3-C#CGGIquudhh?EEr   c                    [        [        U 5      S5        [        [        U5      S5        [        [        U5      S5        [	        U5      n[        [        UR                  5       U R                  UR                  UR                  5      U5      $ )a>  Create a Z3 floating-point conversion expression that represents the
conversion from a floating-point term to a floating-point term of different precision.

>>> x_sgl = FPVal(1.0, Float32())
>>> x_dbl = fpFPToFP(RNE(), x_sgl, Float64())
>>> x_dbl
fpToFP(RNE(), 1)
>>> simplify(x_dbl)
1
>>> x_dbl.sort()
FPSort(11, 53)
DFirst argument must be a Z3 floating-point rounding mode expression.z7Second argument must be a Z3 floating-point expression.0Third argument must be a Z3 floating-point sort.)	r;   r  r  r  rL   rB  rn  rM   r   r  r   r]  rP   s       r   fpFPToFPr{  >*  sf     wr{bcuQxRSz$!ST
3-C&swwy"&&!%%JCPPr   c                    [        [        U 5      S5        [        [        U5      S5        [        [        U5      S5        [	        U5      n[        [        UR                  5       U R                  UR                  UR                  5      U5      $ )zCreate a Z3 floating-point conversion expression that represents the
conversion from a real term to a floating-point term.

>>> x_r = RealVal(1.5)
>>> x_fp = fpRealToFP(RNE(), x_r, Float32())
>>> x_fp
fpToFP(RNE(), 3/2)
>>> simplify(x_fp)
1.5
rx  z5Second argument must be a Z3 expression or real sort.ry  )	r;   r  rr  r  rL   rB  ro  rM   r   rz  s       r   
fpRealToFPr}  R*  sf     wr{bcwqzRSz$!ST
3-C%cggiI3OOr   c                    [        [        U 5      S5        [        [        U5      S5        [        [        U5      S5        [	        U5      n[        [        UR                  5       U R                  UR                  UR                  5      U5      $ )aC  Create a Z3 floating-point conversion expression that represents the
conversion from a signed bit-vector term (encoding an integer) to a floating-point term.

>>> x_signed = BitVecVal(-5, BitVecSort(32))
>>> x_fp = fpSignedToFP(RNE(), x_signed, Float32())
>>> x_fp
fpToFP(RNE(), 4294967291)
>>> simplify(x_fp)
-1.25*(2**2)
rx  rX  ry  )	r;   r  r  r  rL   rB  rp  rM   r   rz  s       r   fpSignedToFPr  d*  sf     wr{bcuQxMNz$!ST
3-C'	266155$((KSQQr   c                    [        [        U 5      S5        [        [        U5      S5        [        [        U5      S5        [	        U5      n[        [        UR                  5       U R                  UR                  UR                  5      U5      $ )aM  Create a Z3 floating-point conversion expression that represents the
conversion from an unsigned bit-vector term (encoding an integer) to a floating-point term.

>>> x_signed = BitVecVal(-5, BitVecSort(32))
>>> x_fp = fpUnsignedToFP(RNE(), x_signed, Float32())
>>> x_fp
fpToFPUnsigned(RNE(), 4294967291)
>>> simplify(x_fp)
1*(2**32)
rx  rX  ry  )	r;   r  r  r  rL   rB  Z3_mk_fpa_to_fp_unsignedrM   r   rz  s       r   fpUnsignedToFPr  v*  sf     wr{bcuQxMNz$!ST
3-C)#'')RVVQUUDHHMsSSr   c                 <   [        5       (       a?  [        [        U 5      S5        [        [        U5      S5        [        [	        U5      S5        [        U5      n[        [        UR                  5       U R                  UR                  UR                  5      U5      $ )zhCreate a Z3 floating-point conversion expression, from unsigned bit-vector to floating-point expression.r  rX  z-Third argument must be Z3 floating-point sort)
r   r;   r  r  r  rL   rB  r  rM   r   r  r  rH   rP   s       r   fpToFPUnsignedr  *  sj    zz72; ef58QR:a="QR
3-C)#'')RVVQUUAEEJCPPr   c           	      D   [        5       (       a?  [        [        U 5      S5        [        [        U5      S5        [        [	        U5      S5        [        U5      n[        [        UR                  5       U R                  UR                  UR                  5       5      U5      $ )a  Create a Z3 floating-point conversion expression, from floating-point expression to signed bit-vector.

>>> x = FP('x', FPSort(8, 24))
>>> y = fpToSBV(RTZ(), x, BitVecSort(32))
>>> print(is_fp(x))
True
>>> print(is_bv(y))
True
>>> print(is_fp(y))
False
>>> print(is_bv(x))
False
r  r  )Third argument must be Z3 bit-vector sort)r   r;   r  r  r  rL   r<  Z3_mk_fpa_to_sbvrM   r   r  r  s       r   fpToSBVr  *  n     zz72; ef58UV:a="MN
3-C%cggiI3OOr   c           	      D   [        5       (       a?  [        [        U 5      S5        [        [        U5      S5        [        [	        U5      S5        [        U5      n[        [        UR                  5       U R                  UR                  UR                  5       5      U5      $ )a  Create a Z3 floating-point conversion expression, from floating-point expression to unsigned bit-vector.

>>> x = FP('x', FPSort(8, 24))
>>> y = fpToUBV(RTZ(), x, BitVecSort(32))
>>> print(is_fp(x))
True
>>> print(is_bv(y))
True
>>> print(is_fp(y))
False
>>> print(is_bv(x))
False
r  r  r  )r   r;   r  r  r  rL   r<  Z3_mk_fpa_to_ubvrM   r   r  r  s       r   fpToUBVr  *  r  r   c                     [        5       (       a  [        [        U 5      S5        [        U5      n[	        [        UR                  5       U R                  5      U5      $ )zCreate a Z3 floating-point conversion expression, from floating-point expression to real.

>>> x = FP('x', FPSort(8, 24))
>>> y = fpToReal(x)
>>> print(is_fp(x))
True
>>> print(is_real(y))
True
>>> print(is_fp(y))
False
>>> print(is_real(x))
False
r  )r   r;   r  rL   r7  Z3_mk_fpa_to_realrM   r   r  rP   s     r   fpToRealr  *  sB     zz58TU
3-C%cggi7==r   c                     [        5       (       a  [        [        U 5      S5        [        U5      n[	        [        UR                  5       U R                  5      U5      $ )a  rief Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format.

The size of the resulting bit-vector is automatically determined.

Note that IEEE 754-2008 allows multiple different representations of NaN. This conversion
knows only one NaN and it will always produce the same bit-vector representation of
that NaN.

>>> x = FP('x', FPSort(8, 24))
>>> y = fpToIEEEBV(x)
>>> print(is_fp(x))
True
>>> print(is_bv(y))
True
>>> print(is_fp(y))
False
>>> print(is_bv(x))
False
r  )r   r;   r  rL   r<  Z3_mk_fpa_to_ieee_bvrM   r   r  s     r   r  r  *  sB    ( zz58TU
3-C)#'')QUU;SAAr   c                   $    \ rS rSrSrS rS rSrg)r  i*  zSequence sort.c                 J    [        U R                  5       U R                  5      $ )z}Determine if sort is a string
>>> s = StringSort()
>>> s.is_string()
True
>>> s = SeqSort(IntSort())
>>> s.is_string()
False
)Z3_is_string_sortr   r   r   s    r   	is_stringSeqSortRef.is_string*  s     !::r   c                 r    [        [        U R                  5       U R                  5      U R                  5      $ r   )rE  Z3_get_seq_sort_basisr   r   rP   r   s    r   basisSeqSortRef.basis +  s%    1$,,.$((KTXXVVr   r   N)r   r   r   r   r   r  r  r   r   r   r   r  r  *  s    	;Wr   r  c                       \ rS rSrSrSrg)r  i+  zCharacter sort.r   Nr  r   r   r   r  r  +  s    r   r  c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ )z>Create a string sort
>>> s = StringSort()
>>> print(s)
String
)rL   r  Z3_mk_string_sortrM   r   s    r   
StringSortr  +  s&     3-C'	2C88r   c                 ^    [        U 5      n [        [        U R                  5       5      U 5      $ )z?Create a character sort
>>> ch = CharSort()
>>> print(ch)
Char
)rL   r  Z3_mk_char_sortrM   r   s    r   CharSortr  +  s%     3-Cswwy1377r   c                 r    [        [        U R                  5       U R                  5      U R                  5      $ )z~Create a sequence sort over elements provided in the argument
>>> s = SeqSort(IntSort())
>>> s == Unit(IntVal(1)).sort()
True
)r  Z3_mk_seq_sortr   r   rP   rG   s    r   SeqSortr  +  s&     nQYY[!%%8!%%@@r   c                   f    \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rS rS rS rSrg)rF  i#+  zSequence expression.c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ r   )r  r  r   r   rP   r   s    r   r]  SeqRef.sort&+  s&    +dllndkkmDdhhOOr   c                     [        X5      $ r   r+  r   s     r   r  SeqRef.__add__)+  s    d""r   c                     [        X5      $ r   r  r   s     r   r  SeqRef.__radd__,+  s    e""r   c                     [        U5      (       a  [        XR                  5      n[        [	        U R                  5       U R                  5       UR                  5       5      U R                  5      $ r   )r   r  rP   rH  Z3_mk_seq_nthr   r   r  s     r   r'  SeqRef.__getitem__/+  sH    1::q((#AM$,,.$++-TVZV^V^__r   c                     [        U5      (       a  [        XR                  5      n[        [	        U R                  5       U R                  5       UR                  5       5      U R                  5      $ r   )r   r  rP   rF  Z3_mk_seq_atr   r   r  s     r   at	SeqRef.at4+  sE    1::q((#Al4<<>4;;=!((*MtxxXXr   c                     [        U R                  5       [        U R                  5       U R                  5       5      5      $ r   )r  r   r  r   r   s    r   r  SeqRef.is_string9+  s(     T\\^T[[]1[\\r   c                 R    [        U R                  5       U R                  5       5      $ r   )Z3_is_stringr   r   r   s    r   is_string_valueSeqRef.is_string_value<+  s    DLLNDKKM::r   c                 L   U R                  5       (       ah  [        R                  5       n[        U R	                  5       U R                  5       [        U5      5      n[        X!R                  S9R                  S5      $ [        U R	                  5       U R                  5       5      $ )z6Return a string representation of sequence expression.r  zlatin-1)r  r'   r(   Z3_get_lstringr   r   r  	string_atr*   decoder   )r   string_lengthcharss      r   r  SeqRef.as_string?+  sp    !!"MMOM"4<<>4;;=%BVWEU)<)<=DDYOO>>r   c                 "    U R                  5       $ r   )r  r   s    r   r"  SeqRef.py_valueG+  s    ~~r   c                     [        [        U R                  5       U R                  5       UR                  5       5      U R                  5      $ r   rH  Z3_mk_str_ler   r   rP   r   s     r   r  SeqRef.__le__J+  1    LWY]YaYabbr   c                     [        [        U R                  5       U R                  5       UR                  5       5      U R                  5      $ r   rH  Z3_mk_str_ltr   r   rP   r   s     r   r  SeqRef.__lt__M+  r  r   c                     [        [        U R                  5       UR                  5       U R                  5       5      U R                  5      $ r   r  r   s     r   r  SeqRef.__ge__P+  1    LWY]YaYabbr   c                     [        [        U R                  5       UR                  5       U R                  5       5      U R                  5      $ r   r  r   s     r   rm  SeqRef.__gt__S+  r  r   r   N)r   r   r   r   r   r]  r  r  r'  r  r  r  r  r"  r  r  r  rm  r   r   r   r   rF  rF  #+  sN    P##`
Y
];? ccccr   rF  c                     [        U [        5      (       a  [        U5      n[        X5      n [	        U 5      (       d  [        S5      eU $ )NzCharacter expression expected)r   rl   rL   CharValr\  r9   chrP   s     r   _coerce_charr  W+  s<    "csmR2;;9::Ir   c                   0    \ rS rSrSrS rS rS rS rSr	g)	rG  i_+  zCharacter expression.c                     [        XR                  5      n[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ r   )r  rP   rH  Z3_mk_char_ler   r   r   s     r   r  CharRef.__le__b+  s?    UHH-M$,,.$++-XZ^ZbZbccr   c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ r   )rH  Z3_mk_char_to_intr   r   rP   r   s    r   to_intCharRef.to_intf+  s'    -dllndkkmLdhhWWr   c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ r   )rH  Z3_mk_char_to_bvr   r   rP   r   s    r   to_bvCharRef.to_bvi+  s'    ,T\\^T[[]KTXXVVr   c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ r   )rH  Z3_mk_char_is_digitr   r   rP   r   s    r   is_digitCharRef.is_digitl+  r  r   r   N)
r   r   r   r   r   r  r  r  r  r   r   r   r   rG  rG  _+  s    dXWZr   rG  c                     [        U5      n[        U [        5      (       a  [        U 5      n [        U [        5      (       d  [        S5      e[        [        UR                  5       U 5      U5      $ )Nz$character value should be an ordinal)	rL   r   rl   ordr   r9   rH  
Z3_mk_charrM   r  s     r   r  r  p+  sT    
3-C"cWb#@AA
3779b1377r   c                     [        U 5      (       d  [        S5      e[        [        U R	                  5       U R                  5       5      U R                  5      $ )NzBit-vector expression needed)r\  r9   rH  Z3_mk_char_from_bvr   r   rP   )r  s    r   
CharFromBvr  x+  s<    2;;899*2::<ErvvNNr   c                 8    [        X5      n U R                  5       $ r   )r  r  r  s     r   CharToBvr  }+  s    	b	B88:r   c                 8    [        X5      n U R                  5       $ r   )r  r  r  s     r   	CharToIntr  +  s    	b	B99;r   c                 8    [        X5      n U R                  5       $ r   )r  r  r  s     r   CharIsDigitr  +  s    	b	B;;=r   c                     [        U [        5      (       a  [        U5      n[        X5      n [	        U 5      (       d  [        S5      e[        U 5      (       d  [        S5      eU $ )Nz#Non-expression passed as a sequencez!Non-sequence passed as a sequence)r   rl   rL   rQ  r\  r9   r%  rO   s     r   r&  r&  +  sQ    !Ssma1::?@@!99=>>Hr   c                     [        U 5      (       a  U R                  $ [        U5      (       a  UR                  $ Uc
  [        5       nU$ r   )r\  rP   r   rj  s      r   	_get_ctx2r  +  s7    qzzuuqzzuu
{jJr   c                 "    [        U [        5      $ )zReturn `True` if `a` is a Z3 sequence expression.
>>> print (is_seq(Unit(IntVal(0))))
True
>>> print (is_seq(StringVal("abc")))
True
)r   rF  r%  s    r   r%  r%  +  s     a  r   c                 P    [        U [        5      =(       a    U R                  5       $ )z\Return `True` if `a` is a Z3 string expression.
>>> print (is_string(StringVal("ab")))
True
)r   rF  r  r%  s    r   r  r  +  s    
 a 2Q[[]2r   c                 P    [        U [        5      =(       a    U R                  5       $ )zreturn 'True' if 'a' is a Z3 string constant expression.
>>> print (is_string_value(StringVal("a")))
True
>>> print (is_string_value(StringVal("a") + StringVal("b")))
False
)r   rF  r  r%  s    r   r  r  +  s     a 8Q%6%6%88r   c                     SR                  S U  5       5      n [        U5      n[        [        UR	                  5       U 5      U5      $ )zcreate a string expressionrY  c              3      #    U  H<  nS [        U5      ::  a  [        U5      S:  a  [        U5      OS[        U5      -  v   M>     g7f)       z\u{%x}N)r  rl   )r@  r  s     r   rA  StringVal.<locals>.<genexpr>+  s:     b`aZ\2R=SWs]B	SQSW@UU`as   AA)joinrL   rF  Z3_mk_stringrM   rO   s     r   rQ  rQ  +  s:    
b`abbA
3-C,swwy!,c22r   c           	          [        U5      n[        [        UR                  5       [	        X5      [        U5      R                  5      U5      $ )zlReturn a string constant named `name`. If `ctx=None`, then the global context is used.

>>> x = String('x')
)rL   rF  ry  rM   rQ   r  r   r  s     r   Stringr  +  s9    
 3-C+cggi4)=z#?R?RSUXYYr   c                     [        U5      n[        U [        5      (       a  U R                  S5      n U  Vs/ s H  n[	        X!5      PM     sn$ s  snf )z$Return a tuple of String constants. r|  )rL   r   rl   r}  r  r  s      r   Stringsr  +  sC    
3-C%C */0%$F4%000r  c                     [        XU5      $ )a(  Extract substring or subsequence starting at offset.

This is a convenience function that redirects to Extract(s, offset, length).

>>> s = StringVal("hello world") 
>>> SubString(s, 6, 5)  # Extract "world"
str.substr("hello world", 6, 5)
>>> simplify(SubString(StringVal("hello"), 1, 3))
"ell"
r3  rH   r1  r2  s      r   	SubStringr  +       1f%%r   c                     [        XU5      $ )a&  Extract substring or subsequence starting at offset.

This is a convenience function that redirects to Extract(s, offset, length).

>>> s = StringVal("hello world")
>>> SubSeq(s, 0, 5)  # Extract "hello"  
str.substr("hello world", 0, 5)
>>> simplify(SubSeq(StringVal("testing"), 2, 4))
"stin"
r  r  s      r   SubSeqr  +  r	  r   c                 L   [        U [        5      (       a8  [        [        U R	                  5       U R
                  5      U R                  5      $ [        U [        5      (       a8  [        [        U R	                  5       U R
                  5      U R                  5      $ [        S5      e)a
  Create the empty sequence of the given sort
>>> e = Empty(StringSort())
>>> e2 = StringVal("")
>>> print(e.eq(e2))
True
>>> e3 = Empty(SeqSort(IntSort()))
>>> print(e3)
Empty(Seq(Int))
>>> e4 = Empty(ReSort(SeqSort(IntSort())))
>>> print(e4)
Empty(ReSort(Seq(Int)))
z9Non-sequence, non-regular expression sort passed to Empty)r   r  rF  Z3_mk_seq_emptyr   r   rP   r  rH  Z3_mk_re_emptyr9   rG   s    r   Emptyr  +  sn     !Z  oaiik1559155AA!Y^AIIK7??
Q
RRr   c                     [        U [        5      (       a8  [        [        U R	                  5       U R
                  5      U R                  5      $ [        S5      e)zCreate the regular expression that accepts the universal language
>>> e = Full(ReSort(SeqSort(IntSort())))
>>> print(e)
Full(ReSort(Seq(Int)))
>>> e1 = Full(ReSort(StringSort()))
>>> print(e1)
Full(ReSort(String))
z8Non-sequence, non-regular expression sort passed to Full)r   r  rH  Z3_mk_re_fullr   r   rP   r9   rG   s    r   Fullr  ,  s?     !Y]199;6>>
P
QQr   c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ )zCreate a singleton sequence)rF  Z3_mk_seq_unitr   r   rP   r%  s    r   Unitr  ,  s&    .ahhj9155AAr   c                     [        X5      n[        X5      n [        X5      n[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )zCheck if 'a' is a prefix of 'b'
>>> s1 = PrefixOf("ab", "abc")
>>> simplify(s1)
True
>>> s2 = PrefixOf("bc", "abc")
>>> simplify(s2)
False
)r  r&  r  Z3_mk_seq_prefixr   r   rP   rj  s      r   PrefixOfr  ,  N     A/CAAAA#AIIKQXXZH!%%PPr   c                     [        X5      n[        X5      n [        X5      n[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )zCheck if 'a' is a suffix of 'b'
>>> s1 = SuffixOf("ab", "abc")
>>> simplify(s1)
False
>>> s2 = SuffixOf("bc", "abc")
>>> simplify(s2)
True
)r  r&  r  Z3_mk_seq_suffixr   r   rP   rj  s      r   SuffixOfr  $,  r  r   c                     [        X5      n[        X5      n [        X5      n[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )zCheck if 'a' contains 'b'
>>> s1 = Contains("abc", "ab")
>>> simplify(s1)
True
>>> s2 = Contains("abc", "bc")
>>> simplify(s2)
True
>>> x, y, z = Strings('x y z')
>>> s3 = Contains(Concat(x,y,z), y)
>>> simplify(s3)
True
)r  r&  r  Z3_mk_seq_containsr   r   rP   rj  s      r   Containsr  3,  sN     A/CAAAA%aiik188:qxxzJAEERRr   c           	      L   [        X 5      nUc  [        U5      (       a  UR                  n[        X5      n[        X#5      n[        X5      n [	        [        UR                  5       U R                  5       UR                  5       UR                  5       5      U R                  5      $ )zmReplace the first occurrence of 'src' by 'dst' in 's'
>>> r = Replace("aaa", "a", "b")
>>> simplify(r)
"baa"
)r  r\  rP   r&  rF  Z3_mk_seq_replacer   r   )rH   srcdstrP   s       r   Replacer$  F,  sz     C
C
{ws||gg
c
C
c
CAA#CKKM188:szz|SZZ\Z\]\a\abbr   c           	         Uc  [        S5      nSn[        U5      (       a  UR                  n[        XU5      n[	        X5      n [	        X5      n[        U5      (       a  [        X#5      n[        [        U R                  5       U R                  5       UR                  5       UR                  5       5      U R                  5      $ )zRetrieve the index of substring within a string starting at a specified offset.
>>> simplify(IndexOf("abcabc", "bc", 0))
1
>>> simplify(IndexOf("abcabc", "bc", 2))
4
Nr   )
r  r\  rP   r  r&  r   r7  Z3_mk_seq_indexr   r   )rH   substrr1  rP   s       r   IndexOfr(  U,  s     ~
Cvjj
As
#CAA%Fv$OAIIKV]]_fmmo^`a`e`effr   c                     Sn[        XU5      n[        X5      n [        X5      n[        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )z4Retrieve the last index of substring within a stringN)r  r&  r7  Z3_mk_seq_last_indexr   r   rP   )rH   r'  rP   s      r   LastIndexOfr+  i,  sW    
C
As
#CAA%F(ahhj&--/RTUTYTYZZr   c                     [        U 5      n [        [        U R                  5       U R	                  5       5      U R
                  5      $ )zWObtain the length of a sequence 's'
>>> l = Length(StringVal("abc"))
>>> simplify(l)
3
)r&  r7  Z3_mk_seq_lengthr   r   rP   rG   s    r   Lengthr.  r,  s2     	AA$QYY[!((*=quuEEr   c                     [        X5      n[        X5      n[        [        UR	                  5       U R                  5       UR                  5       5      U5      $ )z"Map function 'f' over sequence 's')r  r&  rH  Z3_mk_seq_mapr   r   )r  rH   rP   s      r   SeqMapr1  {,  s=    
A/CAAaiik188:qxxzJCPPr   c           	         [        X5      n[        X#5      n[        U5      (       d  [        U5      n[	        [        UR                  5       U R                  5       UR                  5       UR                  5       5      U5      $ )z/Map function 'f' over sequence 's' at index 'i')r  r&  r\  rP  rH  Z3_mk_seq_mapir   r   )r  r<  rH   rP   s       r   SeqMapIr4  ,  sX    
A/CAA1::QKqyy{AHHJ
AHHJWY\]]r   c           	          [        X5      n[        X#5      n[        U5      n[        [	        UR                  5       U R                  5       UR                  5       UR                  5       5      U5      $ r   )r  r&  rP  rH  Z3_mk_seq_foldlr   r   )r  r   rH   rP   s       r   SeqFoldLeftr7  ,  sO    
A/CAAA		QXXZQXXZXZ]^^r   c           
         [        X5      n[        X45      n[        U5      n[        U5      n[        [	        UR                  5       U R                  5       UR                  5       UR                  5       UR                  5       5      U5      $ r   )r  r&  rP  rH  Z3_mk_seq_foldlir   r   )r  r<  r   rH   rP   s        r   SeqFoldLeftIr:  ,  se    
A/CAAAA(ahhj!((*ahhjZ[ZbZbZdegjkkr   c                     [        U 5      n [        [        U R                  5       U R	                  5       5      U R
                  5      $ )zConvert string expression to integer
>>> a = StrToInt("1")
>>> simplify(1 == a)
True
>>> b = StrToInt("2")
>>> simplify(1 == b)
False
>>> c = StrToInt(IntToStr(2))
>>> simplify(1 == c)
False
)r&  r7  Z3_mk_str_to_intr   r   rP   rG   s    r   StrToIntr=  ,  s2     	AA$QYY[!((*=quuEEr   c                     [        U 5      (       d  [        U 5      n [        [        U R	                  5       U R                  5       5      U R                  5      $ )z$Convert integer expression to string)r\  rP  rF  Z3_mk_int_to_strr   r   rP   rG   s    r   IntToStrr@  ,  s9    1::QK"199;
;QUUCCr   c                     [        U 5      (       d  [        U 5      n [        [        U R	                  5       U R                  5       5      U R                  5      $ )z,Convert a unit length string to integer code)r\  rP  r7  Z3_mk_string_to_coder   r   rP   rG   s    r   	StrToCoderC  ,  s9    1::QK(ahhjA155IIr   c                     [        U 5      (       d  [        U 5      n [        [        U R	                  5       U R                  5       5      U R                  5      $ )zConvert code to a string)r\  rP  rF  Z3_mk_string_from_coder   r   rP   rq   s    r   StrFromCoderG  ,  s9    1::QK(ahhjA155IIr   c                     [        X5      n [        [        U R                  5       U R	                  5       5      U R
                  5      $ )zThe regular expression that accepts sequence 's'
>>> s1 = Re("ab")
>>> s2 = Re(StringVal("ab"))
>>> s3 = Re(Unit(BoolVal(True)))
)r&  rH  Z3_mk_seq_to_rer   r   rP   rO   s     r   RerJ  ,  s2     	AAahhj9155AAr   c                       \ rS rSrSrS rSrg)r  i,  zRegular expression sort.c                 r    [        [        U R                  5       U R                  5      U R                  5      $ r   )rE  Z3_get_re_sort_basisr   r   rP   r   s    r   r  ReSortRef.basis,  s%    0JDHHUUr   r   N)r   r   r   r   r   r  r   r   r   r   r  r  ,  s    "Vr   r  c           	         [        U 5      (       aB  [        [        U R                  R	                  5       U R
                  5      U R                  5      $ U b  [        U [        5      (       aP  [        U 5      n[        [        UR	                  5       [        UR	                  5       5      5      U R                  5      $ [        S5      e)NzWRegular expression sort constructor expects either a string or a context or no argument)r  r  Z3_mk_re_sortrP   rM   r   r   ru   rL   r  r9   rO   s     r   ReSortrQ  ,  s    ayyquuyy{AEE:AEEBByJq'**qkswwy2CCGGI2NOQRQVQVWW
o
ppr   c                       \ rS rSrSrS rSrg)rH  i,  zRegular expressions.c                     [        X5      $ r   )Unionr   s     r   r  ReRef.__add__,  s    T!!r   r   N)r   r   r   r   r   r  r   r   r   r   rH  rH  ,  s
    "r   rH  c                 "    [        U [        5      $ r   )r   rH  rG   s    r   r(  r(  ,  s    ar   c                     [        XR                  5      n [        [        U R	                  5       U R                  5       UR                  5       5      U R                  5      $ )zCreate regular expression membership test
>>> re = Union(Re("a"),Re("b"))
>>> print (simplify(InRe("a", re)))
True
>>> print (simplify(InRe("b", re)))
True
>>> print (simplify(InRe("c", re)))
False
)r&  rP   r  Z3_mk_seq_in_rer   r   )rH   res     r   InRerZ  ,  s>     	AvvA?199;
BIIKH!%%PPr   c            
         [        U 5      n [        U 5      n[        5       (       a>  [        US:  S5        [        [	        U  Vs/ s H  n[        U5      PM     sn5      S5        US:X  a  U S   $ U S   R                  n[        U-  " 5       n[        U5       H  nX   R                  5       XE'   M     [        [        UR                  5       X5      U5      $ s  snf )zyCreate union of regular expressions.
>>> re = Union(Re("a"), Re("b"), Re("c"))
>>> print (simplify(InRe("d", re)))
False
r   At least one argument expected.r$  r   )rd   r[   r   r;   r
  r(  rP   r?  r7  r   rH  Z3_mk_re_unionrM   rb   r:  r   rP   r   r<  s         r   rT  rT  ,  s     T?D	TBzz26<=3$/$Qa$/02^_	QwAw
q'++C	rA2Yw~~ 	21377 0   Cc            
         [        U 5      n [        U 5      n[        5       (       a>  [        US:  S5        [        [	        U  Vs/ s H  n[        U5      PM     sn5      S5        US:X  a  U S   $ U S   R                  n[        U-  " 5       n[        U5       H  nX   R                  5       XE'   M     [        [        UR                  5       X5      U5      $ s  snf )zZCreate intersection of regular expressions.
>>> re = Intersect(Re("a"), Re("b"), Re("c"))
r   r\  r$  r   )rd   r[   r   r;   r
  r(  rP   r?  r7  r   rH  Z3_mk_re_intersectrM   r^  s         r   	Intersectrb  -  s     T?D	TBzz26<=3$/$Qa$/02^_	QwAw
q'++C	rA2Yw~~ #CGGIr5s;; 0r_  c                     [        5       (       a  [        [        U 5      S5        [        [	        U R                  5       U R                  5       5      U R                  5      $ )zCreate the regular expression accepting one or more repetitions of argument.
>>> re = Plus(Re("a"))
>>> print(simplify(InRe("aa", re)))
True
>>> print(simplify(InRe("ab", re)))
False
>>> print(simplify(InRe("", re)))
False
expression expected)r   r;   r\  rH  Z3_mk_re_plusr   r   rP   rY  s    r   Plusrg  -  >     zz72; 56rzz|RYY[9266BBr   c                     [        5       (       a  [        [        U 5      S5        [        [	        U R                  5       U R                  5       5      U R                  5      $ )zCreate the regular expression that optionally accepts the argument.
>>> re = Option(Re("a"))
>>> print(simplify(InRe("a", re)))
True
>>> print(simplify(InRe("", re)))
True
>>> print(simplify(InRe("aa", re)))
False
rd  )r   r;   r\  rH  Z3_mk_re_optionr   r   rP   rf  s    r   Optionrk  #-  s>     zz72; 56ryy{;RVVDDr   c                 z    [        [        U R                  5       U R                  5       5      U R                  5      $ )z)Create the complement regular expression.)rH  Z3_mk_re_complementr   r   rP   rf  s    r   
Complementrn  2-  s'    $RZZ\299;?HHr   c                     [        5       (       a  [        [        U 5      S5        [        [	        U R                  5       U R                  5       5      U R                  5      $ )zCreate the regular expression accepting zero or more repetitions of argument.
>>> re = Star(Re("a"))
>>> print(simplify(InRe("aa", re)))
True
>>> print(simplify(InRe("ab", re)))
False
>>> print(simplify(InRe("", re)))
True
rd  )r   r;   r\  rH  Z3_mk_re_starr   r   rP   rf  s    r   Starrq  7-  rh  r   c                     [        5       (       a  [        [        U 5      S5        [        [	        U R                  5       U R                  5       X5      U R                  5      $ )zCreate the regular expression accepting between a lower and upper bound repetitions
>>> re = Loop(Re("a"), 1, 3)
>>> print(simplify(InRe("aa", re)))
True
>>> print(simplify(InRe("aaaa", re)))
False
>>> print(simplify(InRe("", re)))
False
rd  )r   r;   r\  rH  Z3_mk_re_loopr   r   rP   )rY  lohis      r   Looprv  F-  s@     zz72; 56rzz|RYY["A266JJr   c                 &   [        X5      n [        X5      n[        5       (       a*  [        [        U 5      S5        [        [        U5      S5        [	        [        U R                  5       U R                  UR                  5      U R                  5      $ )zCreate the range regular expression over two sequences of length 1
>>> range = Range("a","z")
>>> print(simplify(InRe("b", range)))
True
>>> print(simplify(InRe("bb", range)))
False
rd  )	r&  r   r;   r\  rH  Z3_mk_re_ranger   r   rP   )rt  ru  rP   s      r   Rangery  U-  se     
R	B	R	Bzz72; 5672; 56

bffbff=rvvFFr   c                     [        5       (       a*  [        [        U 5      S5        [        [        U5      S5        [        [	        U R                  5       U R                  UR                  5      U R                  5      $ )z-Create the difference regular expression
    rd  )r   r;   r\  rH  Z3_mk_re_diffr   r   rP   rj  s      r   Diffr|  d-  sQ     zz71:4571:45qyy{AEE1559155AAr   c                 r    [        [        U R                  5       U R                  5      U R                  5      $ )zJCreate a regular expression that accepts all single character strings
    )rH  Z3_mk_re_allcharr   r   rP   )
regex_sortrP   s     r   AllCharr  l-  s*     !*"4"4"6
GXXr   c                 t    [        [        U R                  5       U R                  U5      U R                  5      $ r   )r  Z3_mk_partial_orderr   r   rP   r   rX  s     r   PartialOrderr  t-  s'    *199;uEquuMMr   c                 t    [        [        U R                  5       U R                  U5      U R                  5      $ r   )r  Z3_mk_linear_orderr   r   rP   r  s     r   LinearOrderr  x-  s'    )!))+quueDaeeLLr   c                 t    [        [        U R                  5       U R                  U5      U R                  5      $ r   )r  Z3_mk_tree_orderr   r   rP   r  s     r   	TreeOrderr  |-  s'    '		QUUEBAEEJJr   c                 t    [        [        U R                  5       U R                  U5      U R                  5      $ r   )r  Z3_mk_piecewise_linear_orderr   r   rP   r  s     r   PiecewiseLinearOrderr  -  s*    3AIIKNPQPUPUVVr   c                 r    [        [        U R                  5       U R                  5      U R                  5      $ )zGiven a binary relation R, such that the two arguments have the same sort
create the transitive closure relation R+.
The transitive closure R+ is a new relation.
)r  Z3_mk_transitive_closurer   r   rP   )r  s    r   TransitiveClosurer  -  s'    
 /		QUUCQUUKKr   c                 V    [        U 5      n[        [        R                  U]  U 5        U$ r   )r?  superr'   ri
  r   )r   r   s     r   to_Astr  -  s#    
c(C	&//3(-Jr   c                 V    [        U 5      n[        [        R                  U]  U 5        U$ r   )
ContextObjr  r'   ri
  r   )r   rP   s     r   to_ContextObjr  -  s#    
S/C	&//3(-Jr   c                 V    [        U 5      n[        [        R                  U]  U 5        U$ r   )AstVectorObjr  r'   ri
  r   )r   r   s     r   to_AstVectorObjr  -  s$    SA	&//1&s+Hr   c                     [         n[        [        U5      UR                  5      n[	        [        U5      UR                  5      n[        U5       Vs/ s H  ocU   PM	     nnUR                  XU5        g s  snf r   )_my_hacky_classrH  r  rP   r_   r  r7  	on_clause)rP   r`  r>   depclauseoncr<  depss           r   on_clause_ehr  -  s]    
CVAY(Av.8F!!H%HqFHD%MM!6" &s   A5c                       \ rS rSrS rSrg)OnClausei-  c                     Xl         UR                  U l        X l        SU l        U q[        U R                  R                  5       U R                   R                  U R                  [        5        g )N   )	rH   rP   r  r  r  Z3_solver_register_on_clauserM   rO  _on_clause_eh)r   rH   r  s      r   r   OnClause.__init__-  sG    55"$TXX\\^TVV]]DHHm\r   )rP   r  r  rH   N)r   r   r   r   r   r   r   r   r   r  r  -  s    ]r   r  c                   2    \ rS rSrS rS rS rS rS rSr	g)	PropClosuresi-  c                      0 U l         S U l        g r   baseslockr   s    r   r   PropClosures.__init__-  s    
	r   c                 R    U R                   c  SS KnUR                  5       U l         g g r2   )r  	threadingLock)r   r  s     r   set_threadedPropClosures.set_threaded-  s"    99!(DI r   c                     U R                   (       a&  U R                      U R                  U   nS S S 5        U$ U R                  U   nU$ ! , (       d  f       W$ = fr   r  r  r   rP   r   s      r   r  PropClosures.get-  sL    99JJsO   

3A	  s   A		
Ac                     U R                   (       a$  U R                      X R                  U'   S S S 5        g X R                  U'   g ! , (       d  f       g = fr   r  r  s      r   r^   PropClosures.set-  s7    99"#

3   JJsO s   A
Ac                    U R                   (       a=  U R                      [        U R                  5      S-   nXR                  U'   S S S 5        U$ [        U R                  5      S-   nXR                  U'   U$ ! , (       d  f       W$ = f)Nr   )r  r[   r  )r   r   r
  s      r   r  PropClosures.insert-  sl    99_q(!"

2  	 TZZ1$BJJrN	  	s   'A77
Br  N)
r   r   r   r   r   r  r  r^   r  r   r   r   r   r  r  -  s    )
 r   r  c                  (    [         c  [        5       q g g r   )_prop_closuresr  r   r   r   ensure_prop_closuresr  -  s    % r   c                 Z    [         R                  U 5      nXl        UR                  5         g r   )r  r  cbr(  )rP   r  props      r   user_prop_pushr  -  s     c"DGIIKr   c                 \    [         R                  U 5      nXl        UR                  U5        g r   )r  r  r  r_  )rP   r  rq  r  s       r   user_prop_popr  -  s#    c"DGHHZr   c                 f   [         R                  5         [         R                  U 5      n[        5       n[	        UR
                  5        [        U5      nXCl        [        U[        5      Ul	        SUl
        UR                  U5      n[         R                  UR                  U5        UR                  $ rw  )r  r  r  ru   r   rP   r  r   rs   r   r~   freshr^   r
  )rP   _new_ctxr  nctxnew_ctxnew_props         r   user_prop_freshr  -  s    !c"D9D488H%GH"7,<=DGDJzz$Hx{{H-;;r   c                    [         R                  U 5      nUR                  nXl        [        [	        U5      UR                  5       5      n[        [	        U5      UR                  5       5      nUR                  X#5        XTl        g r   )r  r  r  rH  r  rP   fixed)rP   r  r
  r*   r  old_cbs         r   user_prop_fixedr  -  s]    c"DWWFG	fRj$((*	-B
3EJJrGr   c                     [         R                  U 5      nUR                  nXl        [        [	        U5      UR                  5       5      nUR                  U5        XCl        g r   )r  r  r  rH  r  rP   created)rP   r  r
  r  r  s        r   user_prop_createdr  .  sG    c"DWWFG	fRj$((*	-BLLGr   c                 ~    [         R                  U 5      nUR                  nXl        UR                  5         X2l        g r   )r  r  r  final)rP   r  r  r  s       r   user_prop_finalr  .  s.    c"DWWFGJJLGr   c                    [         R                  U 5      nUR                  nXl        [        [	        U5      UR                  5       5      n[        [	        U5      UR                  5       5      nUR                  X#5        XTl        g r   )r  r  r  rH  r  rP   r   rP   r  r  yr  r  s         r   user_prop_eqr  .  s\    c"DWWFGVAY
+AVAY
+AGGAMGr   c                    [         R                  U 5      nUR                  nXl        [        [	        U5      UR                  5       5      n[        [	        U5      UR                  5       5      nUR                  X#5        XTl        g r   )r  r  r  rH  r  rP   diseqr  s         r   user_prop_diseqr  .  s]    c"DWWFGVAY
+AVAY
+AJJqGr   c                     [         R                  U 5      nUR                  nXl        [        [	        U5      UR                  5       5      nUR                  XsU5        Xel        g r   )r  r  r  rH  r  rP   decide)rP   r  t_refr  phaser  r  r	  s           r   user_prop_decider  &.  sI    c"DWWFGVE]DHHJ/AKKGr   c                    [         R                  U 5      nUR                  nXl        [        [	        U5      UR                  5       5      n[        [	        U5      UR                  5       5      nUR                  Xg5      nXTl        U$ r   )r  r  r  rH  r  rP   binding)	rP   r  q_refinst_refr  r  rZ	  instr   s	            r   user_prop_bindingr  ..  se    c"DWWFGVE]DHHJ/Ax($((*5DQAGHr   c           	         [        U5      n[        5       (       a  [        [        U5      S:  S5        [        U5      S-
  nX   n[        5       (       a  [        [	        U5      S5        [
        U-  " 5       n[        U5       H9  n[        5       (       a  [        [	        X   5      S5        X   R                  XE'   M;     UR                  n[        [        UR                  5       [        X5      X$UR                  5      U5      $ )zCreate a function that gets tracked by user propagator.
Every term headed by this function symbol is tracked.
If a term is fixed and the fixed callback is registered a
callback is invoked that the term headed by this function is fixed.
r   r  r   r  )rd   r   r;   r[   ru  rx  r7  r   rP   r  Z3_solver_propagate_declarerM   rQ   r  s          r   PropagateFunctionr  E.  s     C.Czz3s8a<!BCHqLE
*Czz73<!34%<
C5\::wsv(:;  ''C23779i>RTY`c`g`ghjmnnr   c                       \ rS rSrSS jrS rS rS rS rS r	S	 r
S
 rS rS rS rS rS rS rS rS r/ 4S jr/ / 4S jrSrg)UserPropagateBasei\.  Nc                    Ub  Ub   e[        5         Xl        S U l        S U l        S U l        [
        R                  U 5      U l        S U l        S U l	        S U l
        S U l        S U l        S U l        S U l        U(       a  X l        U(       aR  [        U R!                  5       UR                  ["        R%                  U R                  5      [&        [(        [*        5        g g r   )r  rO  _ctx	fresh_ctxr  r  r  r
  r  r  r   r  r  r  r  Z3_solver_propagate_initr   r'   ri
  _user_prop_push_user_prop_pop_user_prop_fresh)r   rH   rP   s      r   r   UserPropagateBase.__init__e.  s    yCK''	 ''-


 N$T\\^%&XX%+__TWW%=%4%3%57 r   c                 J    U R                   (       a  S U R                   l        g g r   )r  rP   r   s    r   r   UserPropagateBase.__del__~.  s    99 DIIM r   c                 h    U R                   (       a  U R                   $ U R                  R                  $ r   )r  rO  rP   r   s    r   rP   UserPropagateBase.ctx.  s!    >>>>!;;??"r   c                 >    U R                  5       R                  5       $ r   r  r   s    r   r   UserPropagateBase.ctx_ref.  s    xxz~~r   c                     U R                   (       a   eU R                  (       a   eU R                  (       a3  [        U R	                  5       U R                  R                  [
        5        Xl         g r   )r  r  rO  Z3_solver_propagate_fixedr   _user_prop_fixed)r   r  s     r   	add_fixedUserPropagateBase.add_fixed.  C    ::~99};;%dllndkk6H6HJZ[
r   c                     U R                   (       a   eU R                  (       a   eU R                  (       a3  [        U R	                  5       U R                  R                  [
        5        Xl         g r   )r  r  rO  Z3_solver_propagate_createdr   _user_prop_created)r   r  s     r   add_createdUserPropagateBase.add_created.  sD    <<99};;'8J8JL^_r   c                     U R                   (       a   eU R                  (       a   eU R                  (       a3  [        U R	                  5       U R                  R                  [
        5        Xl         g r   )r  r  rO  Z3_solver_propagate_finalr   _user_prop_final)r   r  s     r   	add_finalUserPropagateBase.add_final.  r  r   c                     U R                   (       a   eU R                  (       a   eU R                  (       a3  [        U R	                  5       U R                  R                  [
        5        Xl         g r   )r   r  rO  Z3_solver_propagate_eqr   _user_prop_eq)r   r   s     r   add_eqUserPropagateBase.add_eq.  sB    77{99};;"4<<>4;;3E3E}Ur   c                     U R                   (       a   eU R                  (       a   eU R                  (       a3  [        U R	                  5       U R                  R                  [
        5        Xl         g r   )r  r  rO  Z3_solver_propagate_diseqr   _user_prop_diseq)r   r  s     r   	add_diseqUserPropagateBase.add_diseq.  r  r   c                     U R                   (       a   eU R                  (       a   eU R                  (       a3  [        U R	                  5       U R                  R                  [
        5        Xl         g r   )r  r  rO  Z3_solver_propagate_decider   _user_prop_decide)r   r  s     r   
add_decideUserPropagateBase.add_decide.  sC    ;;99};;&t||~t{{7I7IK\]r   c                     U R                   (       a   eU R                  (       a   eU R                  (       a3  [        U R	                  5       U R                  R                  [
        5        Xl         g r   )r  r  rO  Z3_solver_propagate_on_bindingr   _user_prop_binding)r   r  s     r   add_on_binding UserPropagateBase.add_on_binding.  sD    <<99};;*4<<>4;;;M;MOabr   c                     [        S5      e)Nzpush needs to be overwrittenr8   r   s    r   r(  UserPropagateBase.push.  s    899r   c                     [        S5      e)Nzpop needs to be overwrittenr8   )r   rq  s     r   r_  UserPropagateBase.pop.  s    788r   c                     [        S5      e)Nzfresh needs to be overwrittenr8   )r   r  s     r   r  UserPropagateBase.fresh.  s    9::r   c                 D   U R                   (       a   eU R                  (       a:  [        U R                  5       U R                  R                  UR                  5        g [        U R                  5       [        R                  U R                  5      UR                  5        g r   )	r  rO  Z3_solver_propagate_registerr   r   Z3_solver_propagate_register_cbr'   ri
  r  )r   rr   s     r   r(  UserPropagateBase.add.  s[    99};;(9K9KQUUS+DLLNFOODGG<TVWV[V[\r   c                     [        U R                  5       [        R                  U R                  5      UR
                  X#5      $ r   )Z3_solver_next_splitr   r'   ri
  r  r   )r   r	  r  r  s       r   
next_splitUserPropagateBase.next_split.  s+    #DLLNFOODGG4LaeeUX``r   c           
      n   [        U5      u  pE[        U5      n[        U VVs/ s H  u  pxUPM	     snn5      u  p[        U VVs/ s H  u  pxUPM	     snn5      u  p[        UR                  R	                  5       [
        R                  U R                  5      XTXiXR                  5      $ s  snnf s  snnf r   )	r@  r[   Z3_solver_propagate_consequencerP   rM   r'   ri
  r  r   )r   rr   idseqs_ids	num_fixednum_eqsr  r  _lhs_num_lhs_rhs_num_rhss                r   	propagateUserPropagateBase.propagate.  s    ',c(&c':cdac':;&c':cdac':;.quuyy{FOOGG=wdEEC 	C (;':s   B+
B1
c                 X    U R                  [        SU R                  5       5      X5        g rw  )r9  r  rP   )r   r  r1  s      r   conflictUserPropagateBase.conflict.  s    wudhhj14=r   )r  r  r  r  r  r  r   r  r  r  r
  rO  r   )r   r   r   r   r   r   rP   r   r  r  r
  r  r  r  r  r(  r_  r  r(  r,  r9  r<  r   r   r   r   r  r  \.  sk    72!# :9;]a %' C ! >r   r  r   )r   NrF  )r&  N)r  Nr  r  )l    N)r   r	  (5  r   rY  r   z3typesz3consts	z3printer	fractionsr   r!
  r  r  r	  r"
  r,   typingr   r	   collections.abcr
   r   r   r   r   r   r    r#   r0   r3   r6   r;   r@   rD   rI   rQ   rX   rd   rg   ro   rs   ru   r   r   rL   r   r   r   r   r   r   r   rk   r  r   r   r,  r2  r4  r=  r@  rB  r   rK  rM  ru  rE  r  r  r  r  r  r  r  r  rG  r  r  r  r/  rH  rN  r  rZ  r^  r\  r  rc  rf  ri  rk  rq  ru  rw  rz  r  r  r  r  r  rz  r  r  r   r   r  r  r  r  r   r  r'  r  r  r  r  r  r  r  r  r  r  r  r  r2  r  r  r  r4  rX  rf  rj  rl  ro  r}  r{  r7  r  r  rr  r@  r9  r  r  r  r  r  r  r  r  r  r  r   r  r  r	  r  r  r6  r8  r:  rP  r^  r  rd  r  rS  rk  rm  ro  rq  rs  rv  rx  rz  r|  r~  r~  r  r  r  r  r  r  r<  r;  r  r  r  r  r  r  r  r!  r+  r3  r5  r8  r<  r?  rB  rE  rI  rL  rO  rR  rU  r[  r^  ra  rd  rg  rl  rp  rt  rw  rz  r}  r  r  r  r=  r%  r  r  r  r  r  r  r  rl  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r)  r  r  r>  rd  ri  rl  ru  rw  r  r   r  r_   rB  rl  r  r  r  r  r  r  r7  rE  rB  rF  rC  
Z3_L_UNDEFrD  r&  r	  r	  r!	  r  r	  r	  rD  r	  rC  r	  r	  r	  r	  r	  on_model_eh_typerj
  r	  ro
  r
  rn  r
  r
  r
  r
  r
  r
  r
  r
  r
  r
  r
  r
  r
  r
  r
  r
  r
  rm  r0  r  r  r!  r#  r%  r  r  r-  r0  ro  ri  r8  r;  rJ  rM  rR  rY  r_  ra  rg  rj  rl  rr  rv  rz  r}  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  	frozensetr  r  r  r  r  r  r  r  r  r  r  r  r  r   r  r  r  r  r  r  r  r  r  rB  rE  rf  r  rl  r  rq  r  rw  r  r|  r  r  r  rA  r  r  r  r  r  r  r  r  r  r  r  r  r	  r  r  rN  r  r  r  r  r!  r#  r7  r?  rE  rR  r\  r2  r6  r9  r=  r@  rC  rF  rI  rL  rO  rR  rV  rX  r,  r(  r3  r0  re  rg  rk  rt  rv  r{  r}  r  r  r  r  r  r  r  r  r  r  r  r  rF  r  rG  r  r  r  r  r  r&  r  r%  r  r  rQ  r  r  r  r  r  r  r  r  r  r  r$  r(  r+  r.  r1  r4  r7  r:  r=  r@  rC  rG  rJ  r  rQ  rH  r(  rZ  rT  rb  rg  rk  rn  rq  rv  ry  r|  r  r  r  r  r  r  r  r  r  r  r  Z3_on_clause_ehr  r  r  r  r  r  r  r  r  r  r  r  r  r  r  
Z3_push_ehr  	Z3_pop_ehr  Z3_fresh_ehr  Z3_fixed_ehr  Z3_created_ehr  Z3_final_ehr	  Z3_eq_ehr  r  Z3_decide_ehr  Z3_on_binding_ehr  r  r  r   r   r   <module>rQ     sj  $J       
 	  Q) $  
 A*"@>!
C

;2 4L 4Lp 	' *W G 0 #
B* nZ nb!s !t !*6 v $ &)G ) ) )($ *Y%f Y%x
" 
" 
">8 8S 8W 8SG S$ Q"A]& A]H
&c.X&g$9Dcf cJ/d&*	&".24+&<2<B
'[.>0#	U1MEc Ew E7 E# #7 #	/S 	/$!' !H-g -d" " "$$ $ $$% % %	#s 	#t 	#	"c 	"d 	"	'3 	'4 	'	#s 	#t 	#"c "d "	(C 	(D 	(8$4&	Y/ =QJF >&=B<N	< 	<%$?0!@G @F( 01brB\^  HF 2B T$ 2B U*[6I.7 I.X'c 'd ' ZSw ZSz#*& &&'&+0I0J,L	#s 	#t 	#	#s 	#t 	#	#s 	#t 	##s #t #"	$ 	$ 	$	#s 	#t 	#	"c 	"d 	"	"c 	"d 	"	"c 	"d 	"	"c 	"d 	"	&# 	&$ 	&'3 '4 '&# &$ &! !HaD aDHAh ADF8"9"		XQ&7 
+
Y
.
AQ
Z/BR@(@$="

&(G (B(ZX ZXz-9 -b$7I.I<f"P05*+\3Olh
L$L$L$L$O*O*O*O@X Y H<H8F0ED`YXaYL`YY7 Y6/Zw /ZdW[# # #
+
+) -0OBNZ@" A.L,	QT
&	%$$
<;
@
DKKFRMM"YU* U*p	7 	7	< 	<]@^
g ^
BU' UV
	Z	VB+B +B\.1E 1EtkJ: kJh	WD
 WD@tN tNzj$ j$Zs# s#lW(z W(t
 2 N
R|! |!J, ,^ Yz"

$Z
Z Z
zJ*
@&A* A*T	L' 	LS.	?g 	?
*D D4YB,5 5@ 

   01i
z i
bTE* TEx/i /irOa OadRQ(
*?&V  
RRG*G\0:&RE REj Z/9&0/B,I(W"I22
V
XBV(],>4>2"
?$@$)(FFF<>802( $` `(  " k*  rt i& 8      %% !?*$%6 4  4F8:8<8<9?.' .$&o"G o"d?g ?I
I
I
I
D
D
D
D
@
@

"4O1u O1d 2C)X>"E"DHFEI+E\P05&<.< =2I<>U4"44455584A	7<8:=<<l
	4	5	4	5	4	 J:$iNF"Q(P$R$T$QP,P,>(B@W W"' 98A1cW 1chZg Z"8O
!3 3 39s 9t 93Z1&&S(RB
QQS&cg([FQ^_lF DJJBV Vq"G " Q8(<$CEI
CKGBYNMKWL

 #  -] ]! !H ( ^,=)/ / "#45 / &O,  !12 %&78 o.D> D>r   