
    *-h{,                         S r SSKrSSK7  SS jrSS jrS r S rS	 rSS
 jrS r	SS jr
S rSS jrSS jrS rS rS rS rS rS rSS jrg)z"
Usage:
import common_z3 as CM_Z3
    N   )*c                 ^    S nS nUc	  U" U 5      nOU" X5      nU(       a  [        U5      $ U$ )z
order preserving

>>> vset([[11,2],1, [10,['9',1]],2, 1, [11,2],[3,3],[10,99],1,[10,['9',1]]],idfun=repr)
[[11, 2], 1, [10, ['9', 1]], 2, [3, 3], [10, 99]]
c              3   @   #    0 nU  H  nX!;  d  M
  S X'   Uv   M     g 7fN )seqd_ss      C/home/james-whalen/.local/lib/python3.13/site-packages/z3/z3util.py_uniq_normalvset.<locals>._uniq_normal   s%     A{ s   c              3   P   #    0 nU  H  nU" U5      nXB;  d  M  S X$'   Uv   M     g 7fr   r   )r	   idfunr
   r   h_s        r   _uniq_idfunvset.<locals>._uniq_idfun$   s.     AqB|	 s   &&)list)r	   r   as_listr   r   ress         r   vsetr      s8     }3#%49(S(    c                 r   [         R                  " S5      n[         R                  " S5      n[         R                  " S5      n[         R                  " S5      n[        XX45        [        [        UR
                  UR
                  UR
                  UR
                  45      nU (       a  SR                  " U6 $ U$ )Nr   z{}.{}.{}.{})ctypesc_uintZ3_get_versionmapintvalueformat)as_strmajorminorbuildrevrss         r   get_z3_versionr'   4   s    MM!EMM!EMM!E
--
C5,	S5;;U[[#))D	EB##R((	r   c                     [        5       (       a  [        U 5      (       d   eSR                  [        U 5      U R	                  5       U R                  5       5      $ )a  
Returns a 'stronger' hash value than the default hash() method.
The result from hash() is not enough to distinguish between 2
z3 expressions in some cases.

Note: the following doctests will fail with Python 2.x as the
default formatting doesn't match that of 3.x.
>>> x1 = Bool('x'); x2 = Bool('x'); x3 = Int('x')
>>> print(x1.hash(), x2.hash(), x3.hash()) #BAD: all same hash values
783810685 783810685 783810685
>>> print(ehash(x1), ehash(x2), ehash(x3))
x_783810685_1 x_783810685_1 x_783810685_2

z{}_{}_{})z3_debugis_exprr    strhash	sort_kindvs    r   ehashr0   A   s>     zzqzzzSVQVVXq{{}==r   c                 p    [        U 5      =(       a%    U R                  5       R                  5       [        :H  $ )a  
EXAMPLES:

>>> is_expr_var(Int('7'))
True
>>> is_expr_var(IntVal('7'))
False
>>> is_expr_var(Bool('y'))
True
>>> is_expr_var(Int('x') + 7 == Int('y'))
False
>>> LOnOff, (On,Off) = EnumSort("LOnOff",['On','Off'])
>>> Block,Reset,SafetyInjection=Consts("Block Reset SafetyInjection",LOnOff)
>>> is_expr_var(LOnOff)
False
>>> is_expr_var(On)
False
>>> is_expr_var(Block)
True
>>> is_expr_var(SafetyInjection)
True
is_constdeclkindZ3_OP_UNINTERPRETEDr.   s    r   is_expr_varr7   \   s%    0 A;A1668==?.AAAr   c                 p    [        U 5      =(       a%    U R                  5       R                  5       [        :g  $ )a  
EXAMPLES:

>>> is_expr_val(Int('7'))
False
>>> is_expr_val(IntVal('7'))
True
>>> is_expr_val(Bool('y'))
False
>>> is_expr_val(Int('x') + 7 == Int('y'))
False
>>> LOnOff, (On,Off) = EnumSort("LOnOff",['On','Off'])
>>> Block,Reset,SafetyInjection=Consts("Block Reset SafetyInjection",LOnOff)
>>> is_expr_val(LOnOff)
False
>>> is_expr_val(On)
True
>>> is_expr_val(Block)
False
>>> is_expr_val(SafetyInjection)
False
r2   r.   s    r   is_expr_valr9   w   s%    . A;A1668==?.AAAr   c                    Uc  / n[        5       (       a  [        U 5      (       d   e[        U 5      (       a%  [        U 5      (       a  U$ [	        X/-   [
        5      $ U R                  5        H  n[        X!5      nM     [	        U[
        5      $ )z
>>> x,y = Ints('x y')
>>> a,b = Bools('a b')
>>> get_vars(Implies(And(x+y==0,x*2==10),Or(a,Implies(a,b==False))))
[x, y, a, b]

)r)   r*   r3   r9   r   r+   childrenget_vars)fr&   f_s      r   r<   r<      su     
zzzqzzz{{q>>IS#&& **,B"!B  B}r   c                 d   UR                  5       [        :X  a  [        U 5      nU$ UR                  5       [        :X  a  [	        U 5      nU$ UR                  5       [
        :X  a  [        U 5      nU$ UR                  5       [        :X  a  [        X5      nU$ [        SXR                  5       4-  5      e)Nz%Cannot handle this sort (s: %sid: %d))
r5   Z3_INT_SORTIntZ3_REAL_SORTRealZ3_BOOL_SORTBoolZ3_DATATYPE_SORTConst	TypeError)namevsortr/   s      r   mk_varrK      s    zz|{"I H 
	%J H 
	%J H 
)	)$ H ?5**,BWWXXr   c                 N  ^^ [        5       (       a  T(       a  [        T5      (       d   eU nT(       aI  [        5       (       a.  [        [        T5      5      u  pEUU4S jnUSL d   U" 5       5       e[	        TU5      nTS:  aB  [        S5        [        T5        [        S5        [        U 5        [        S5        [        U5        [        U5      n[        USS9nUc  [        S	5        g
USL a  g[        5       (       a  [        U[        5      (       d   eU(       a  SUS   4$ S/ 4$ )a  
>>> r,m = prove(BoolVal(True),verbose=0); r,model_str(m,as_str=False)
(True, None)

#infinite counter example when proving contradiction
>>> r,m = prove(BoolVal(False)); r,model_str(m,as_str=False)
(False, [])

>>> x,y,z=Bools('x y z')
>>> r,m = prove(And(x,Not(x))); r,model_str(m,as_str=True)
(False, '[]')

>>> r,m = prove(True,assume=And(x,Not(x)),verbose=0)
Traceback (most recent call last):
...
AssertionError: Assumption is always False!

>>> r,m = prove(Implies(x,x),assume=y,verbose=2); r,model_str(m,as_str=False)
assume:
y
claim:
Implies(x, x)
to_prove:
Implies(y, Implies(x, x))
(True, None)

>>> r,m = prove(And(x,True),assume=y,verbose=0); r,model_str(m,as_str=False)
(False, [(x, False), (y, True)])

>>> r,m = prove(And(x,y),assume=y,verbose=0)
>>> print(r)
False
>>> print(model_str(m,as_str=True))
x = False
y = True

>>> a,b = Ints('a b')
>>> r,m = prove(a**b == b**a,assume=None,verbose=0)
E: cannot solve !
>>> r is None and m is None
True

c                  <   > Sn TS:  a  SR                  TU 5      n U $ )NzAssumption is always False!   z{}
{})r    )emsgassumeverboses    r   _fprove.<locals>._f   s$    4a<#??648Dr   FrN   zassume: zclaim: z
to_prove: r   kzE: cannot solve !)NN)TNr   )	r)   r*   proveNotImpliesprint
get_models
isinstancer   )	claimrP   rQ   to_prove	is_proved_rR   r=   modelss	    ``      r   rV   rV      s    Z zzWV__,,H:: V-LI %+rt+%68,!|jfielhHAQF~!"	5::fd++++&)##"9r   c           
      b   [        5       (       a  [        U 5      (       d   eUS:  d   e[        5       nUR                  U 5        / nSnUR	                  5       [
        :X  a  XA:  a  US-   nUR                  5       nU(       d  OoUR                  U5        [        [        U Vs/ s H  of" 5       XV   :H  PM     sn5      5      nUR                  U5        UR	                  5       [
        :X  a  XA:  a  M  UR	                  5       [        :X  a  gUR	                  5       [        :X  a  US:X  a  gU$ s  snf )a  
Returns the first k models satisfying f.
If f is not satisfiable, returns False.
If f cannot be solved, returns None
If f is satisfiable, returns the first k models
Note that if f is a tautology, e.g.\ True, then the result is []

Based on http://stackoverflow.com/questions/11867611/z3py-checking-all-solutions-for-equation

EXAMPLES:
>>> x, y = Ints('x y')
>>> len(get_models(And(0<=x,x <= 4),k=11))
5
>>> get_models(And(0<=x**y,x <= 1),k=2) is None
True
>>> get_models(And(0<=x,x <= -1),k=2)
False
>>> len(get_models(x+y==7,5))
5
>>> len(get_models(And(x<=5,x>=1),7))
5
>>> get_models(And(x<=0,x>=5),7)
False

>>> x = Bool('x')
>>> get_models(And(x,Not(x)),k=1)
False
>>> get_models(Implies(x,x),k=1)
[]
>>> get_models(BoolVal(True),k=1)
[]



r   r   NF)r)   r*   SolveraddchecksatmodelappendrW   Andunknownunsat)r=   rU   r   r`   imr/   blocks           r   rZ   rZ     s    J zzqzzzAvvAEE!HF	A
'')s
quEGGIa Ca0aa012	e '')s
qu 	wwyG	
e	Q 1s   "D,c                     [        U SUS9S   $ )z
>>> is_tautology(Implies(Bool('x'),Bool('x')))
True

>>> is_tautology(Implies(Bool('x'),Bool('y')))
False

>>> is_tautology(BoolVal(True))
True

>>> is_tautology(BoolVal(False))
False

Nr\   rP   rQ   r   )rV   r\   rQ   s     r   is_tautologyrq   U  s     uT7;A>>r   c                 0    [        [        U 5      SUS9S   $ )a  
>>> x,y=Bools('x y')
>>> is_contradiction(BoolVal(False))
True

>>> is_contradiction(BoolVal(True))
False

>>> is_contradiction(x)
False

>>> is_contradiction(Implies(x,y))
False

>>> is_contradiction(Implies(x,x))
False

>>> is_contradiction(And(x,Not(x)))
True
Nro   r   )rV   rW   rp   s     r   is_contradictionrs   g  s    , s5z$@CCr   c                 ^    [        U SS9n[        U[        5      (       a  [        U5      S:H  $ g)a  
return True if f has exactly 1 model, False otherwise.

EXAMPLES:

>>> x, y = Ints('x y')
>>> exact_one_model(And(0<=x**y,x <= 0))
False

>>> exact_one_model(And(0<=x,x <= 0))
True

>>> exact_one_model(And(0<=x,x <= 1))
False

>>> exact_one_model(And(0<=x,x <= -1))
False
rN   rT   r   F)rZ   r[   r   len)r=   r`   s     r   exact_one_modelrv     s/    ( QF&$6{ar   c                 :   [        5       (       a   U [        :X  d  U [        :X  d  U [        :X  d   e[	        U5      S:X  a5  [        US   [        5      (       d  [        US   [        5      (       a  US   n[        5       (       a  [        S U 5       5      (       d   eU Vs/ s H  n[        U5      (       d  M  UPM     nnU(       aP  [	        U5      S:X  a  US   $ U [        :X  a  [        U5      $ U [        :X  a  [        U5      $ [        US   US   5      $ gs  snf )a  
>>> myAnd(*[Bool('x'),Bool('y')])
And(x, y)

>>> myAnd(*[Bool('x'),None])
x

>>> myAnd(*[Bool('x')])
x

>>> myAnd(*[])

>>> myAnd(Bool('x'),Bool('y'))
And(x, y)

>>> myAnd(*[Bool('x'),Bool('y')])
And(x, y)

>>> myAnd([Bool('x'),Bool('y')])
And(x, y)

>>> myAnd((Bool('x'),Bool('y')))
And(x, y)

>>> myAnd(*[Bool('x'),Bool('y'),True])
Traceback (most recent call last):
...
AssertionError
r   r   c              3   L   #    U  H  n[        U[        5      (       + v   M     g 7fr   )r[   bool).0vals     r   	<genexpr>myBinOp.<locals>.<genexpr>  s     :z#t,,,s   "$N)r)   Z3_OP_OR	Z3_OP_ANDZ3_OP_IMPLIESru   r[   r   tupleallr*   Orrh   rX   )opLr{   s      r   myBinOpr     s    > zzX~yB-4GGG
1v{
1Q4..*QqT52I2IaDzz::::::*WS\A*q6Q;Q4K>a5L?q6MqtQqT"" 	+s    D8Dc                  "    [        [        /U Q76 $ r   )r   r   r   s    r   myAndr     s    9!q!!r   c                  "    [        [        /U Q76 $ r   )r   r~   r   s    r   myOrr     s    8 a  r   c                 $    [        [        X/5      $ r   )r   r   )abs     r   	myImpliesr     s    =1&))r   c                 Z    [        [        U S   U S   5      [        U S   U S   5      5      $ )Nr   r   )rh   rX   )r=   s    r   Iffr     s-    wqtQqT"GAaD!A$$788r   c           
      h   [        5       (       a   U b  U / :X  d  [        U [        5      (       d   eU (       a^  U  Vs/ s H  o"X   4PM
     nn[        US S9nU(       a5  SR	                  U VVs/ s H  u  pBSR                  XB5      PM     snn5      $ U$ U(       a  [        U 5      $ U $ s  snf s  snnf )z
Returned a 'sorted' model (so that it's easier to see)
The model is sorted by its key,
e.g. if the model is y = 3 , x = 10, then the result is
x = 10, y = 3

EXAMPLES:
see doctest examples from function prove()

c                     [        U 5      $ r   )r+   )r   r_   s     r   <lambda>model_str.<locals>.<lambda>  s    Qr   )key
z{} = {})r)   r[   ModelRefsortedjoinr    r+   )rl   r!   r/   vsrU   s        r   	model_strr     s     zzyAGz!X'>'>>>!"#A!$i#B/0992F2!i..q42FGGIs1v&Q& $ Gs   B).B.
)NT)Fr   )Nr   )r   )T)__doc__r   z3r   r'   r0   r7   r9   r<   rK   rV   rZ   rq   rs   rv   r   r   r   r   r   r   r   r   r   <module>r      sy   
  )D
>*B6B46Vr>B?$D262j"!*9'r   