z3.parse_smt2_string fails on int2bv - python

When I use parse_smt2_string on the example string from the docs, it works correctly. However, the parsing fails on int2bv. How can I diagnose this?
>>> import z3
>>> z3.parse_smt2_string('(declare-const x Int) (assert (> x 0)) (assert (< x 10))')
[x > 0, x < 10]
>>> z3.parse_smt2_string('((_ int2bv 1) 1)')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/elliot/miniconda3/envs/angr/lib/python3.6/site-packages/z3_solver-4.8.7.0-py3.6-linux-x86_64.egg/z3/z3.py", line 8601, in parse_smt2_string
return AstVector(Z3_parse_smtlib2_string(ctx.ref(), s, ssz, snames, ssorts, dsz, dnames, ddecls), ctx)
File "/home/elliot/miniconda3/envs/angr/lib/python3.6/site-packages/z3_solver-4.8.7.0-py3.6-linux-x86_64.egg/z3/z3core.py", line 3222, in Z3_parse_smtlib2_string
_elems.Check(a0)
File "/home/elliot/miniconda3/envs/angr/lib/python3.6/site-packages/z3_solver-4.8.7.0-py3.6-linux-x86_64.egg/z3/z3core.py", line 1381, in Check
raise self.Exception(self.get_error_message(ctx, err))
z3.z3types.Z3Exception: b'(error "line 1 column 2: invalid command, symbol expected")\n'

This has nothing to do with int2bv, but rather due to the fact that you've not provided a line that is valid SMTLib at the top-level. The following, for instance, works:
>>> z3.parse_smt2_string('(assert (= #b1 ((_ int2bv 1) 1)))')
[1 == int2bv(1)]
At the top-level, you can have declarations, assertions, or general SMTLib commands, not a standalone expression.

Related

Is the function "next" a good practice to find first occurrence in a iterable?

I've learned about iterators and such and discovered this quite interesting way of getting the first element in a list that a condition is applied (and also with default value in case we don't find it):
first_occurence = next((x for x in range(1,10) if x > 5), None)
For me, it seems a very useful, clear way of obtaining the result.
But since I've never seen that in production code, and since next is a little more "low-level" in the python structure I was wondering if that could be bad practice for some reason. Is that the case? and why?
It's fine. It's efficient, it's fairly readable, etc.
If you're expecting a result, or None is a possible result (so using None as a placeholder makes it hard to figure out if you got a result or got the default) it may be better to use the EAFP form rather than providing a default, catching the StopIteration it raises if no item is found, or just letting it bubble up if the problem is from the caller's input not meeting specs (so it's up to them to handle it). It looks even cleaner at point of use that way:
first_occurence = next(x for x in range(1,10) if x > 5)
Alternatively, when None is a valid result, you can use an explicit sentinel object that's guaranteed unique like so:
sentinel = object() # An anonymous object you construct can't possibly appear in the input
first_occurence = next((x for x in range(1,10) if x > 5), sentinel)
if first_occurence is not sentinel: # Compare with is for performance and to avoid broken __eq__ comparing equal to sentinel
A common use case for this one of these constructs to replace a call to any when you not only need to know if any item passed the test, but which item (any can only return True or False, so it's unsuited to finding which item passed).
We can wrap it up in a function to provide an even nicer interface:
_raise = object()
# can pass either an iterable or an iterator
def first(iterable, condition, *, default=_raise, exctype=None):
"""Get the first value from `iterable` which meets `condition`.
Will consume elements from the iterable.
default -> if no element meets the condition, return this instead.
exctype -> if no element meets the condition and there is no default,
raise this kind of exception rather than `StopIteration`.
(It will be chained from the original `StopIteration`.)
"""
try:
# `iter` is idempotent; this makes sure we have an iterator
return next(filter(condition, iter(iterable)))
except StopIteration as e:
if default is not _raise:
return default
if exctype:
raise exctype() from e
raise
Let's test it:
>>> first(range(10), lambda x: x > 5)
6
>>> first(range(10), lambda x: x > 11)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in first
StopIteration
>>> first(range(10), lambda x: x > 11, exctype=ValueError)
Traceback (most recent call last):
File "<stdin>", line 4, in first
StopIteration
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 9, in first
ValueError
>>> first(range(10), lambda x: x > 11, default=None)
>>>

Python all short-circuiting with None element

I read everywhere that Python all and any functions support short-circuiting.
However:
a = None
all((a is not None, a + 1 > 2))
Throws the following error:
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/IPython/core/interactiveshell.py", line 3331, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-4-6e28870e65c8>", line 1, in <module>
all((a is not None, a + 1 > 2))
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
I would have expected the code not to evaluate a + 1 > 2 since a is None.
Why is this happening? Is this because each term is evaluated before the call? Am I forced to use the and operator as in a is not None and a + 1 > 2?
The tuple (a is not None, a + 1 > 2) needs to be created before all() can be called. It is during the creation of the tuple that the TypeError is raised. all() doesn't even get a chance to run.
If you want to see all's short circuiting in action, pass it a generator expression. For example:
>>> all('foobaR'[i].islower() for i in range(7))
False
>>> all('foobar'[i].islower() for i in range(7))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <genexpr>
IndexError: string index out of range
In the first run all stops when it hits the 'R'.islower() case since that's False. In the second run it keeps going until i == 6, which triggers an index error.
Am I forced to use the and operator as in a is not None and a + 1 > 2?
I wouldn't say "forced"—I'm sure there other convoluted options—but yes, that's the obvious and idiomatic way to write it.

Problem with mpmath under Python 3.8, but OK under 2.7

The following lttle program fails using Python 3.8, but is OK under 2.7:
from mpmath import mpf, nsum
def z(n):
x = [mpf(1) for k in range(1,n)]
return 99
print (nsum(z, [2,2]))
The code looks odd, as it is pared down from a rather larger program. I can't pare it down any further. This can be confirmed easily using the interactive shell at https://www.python.org/shell/
The error report is:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.8/site-packages/mpmath/calculus/extrapolation.py", line 1698, in nsum
return +g()
File "/usr/lib/python3.8/site-packages/mpmath/calculus/extrapolation.py", line 1745, in <lambda>
return False, lambda: f(*([0]*len(intervals)))
File "/usr/lib/python3.8/site-packages/mpmath/calculus/extrapolation.py", line 1777, in g
s += f(*args)
File "<stdin>", line 2, in z
TypeError: 'mpf' object cannot be interpreted as an integer
Have I missed something obvious?
nsum passes n as mpf to z, but range expects:
...int or any object that implements the __index__ special method.
So you could cast n explicitly to int, e.g.:
x = [mpf(1) for k in range(1, int(n))]

Why does the timeit() function return different results when handed a function vs a string expression?

I'm trying out the python timeit function in my Python REPL. It can time small pieces of code in two ways: Either as a callable, or as a quoted expression. I'd like to know why the following code produces different timing results.
>>> import timeit
>>> timeit.timeit("lambda *args: None")
0.058281898498535156
>>> timeit.timeit(lambda *args: None)
0.0947730541229248
>>>
My intuition tells me that there should be more 'overhead' associated with the quoted string variant because it requires interpretation, but this does not appear to be the case. But apparently my intuition is mistaken..
Here's another code snippet. There does not appear a huge time difference between invoking the callable function vs. timing the quoted function statement:
>>> def costly_func():
... return list(map(lambda x: x^2, range(10)))
...
>>> import timeit
>>> timeit.timeit(costly_func)
2.421797037124634
>>> timeit.timeit("list(map(lambda x: x^2, range(10)))")
2.3588619232177734
Observe:
>>> def costly():
... return list(map(str, list(range(1_000_000))))
...
>>> timeit.timeit(costly, number=100)
30.65105245400082
>>> timeit.timeit('costly', number=1_000_000_000, globals=globals())
27.45540758000061
Look at the number argument. It took 30 seconds to execute the function costly 100 times. It took almost 30 seconds to execute the expression costly 1'000'000'000 (!) times.
Why? Because the second code does not execute the function costly! The only thing it executes is the expression costly: notice the lack of parentheses, which means it's not a function call. The expression costly is basically a no-op (well, it just requires checking whether the name "costly" exists in the current scope, that's all), that's why it's so fast, and if Python was smart enough to optimise it away, the execution of the expression costly (not costly()!) would be instantaneous!
In your case, saying lambda *args: None is simply defining an anonymous function, right? When you execute this exact code, a new function is created, but not executed (in order to do that, you should call it: (lambda *args: None)()).
So, timing the string "lambda *args: None" with timeit.timeit("lambda *args: None") basically tests how fast Python can spit out new anonymous functions.
Timing the function itself with timeit.timeit(lambda *args: None) tests how fast Python can execute an existing function.
Spitting out newly created functions is a piece of cake, while actually running them can be really hard.
Take this code for example:
def Ackermann(m, n):
if m == 0:
return n + 1
if m > 0:
if n == 0:
return Ackermann(m - 1, 1)
elif n > 0:
return Ackermann(m - 1, Ackermann(m, n - 1))
If you put that exact code in a string and timeit it, you'll get something like this:
>>> code = """def Ackermann(m, n):
... if m == 0:
... return 0
... if m > 0:
... if n == 0:
... return Ackermann(m - 1, 1)
... elif n > 0:
... return Ackermann(m - 1, Ackermann(m, n - 1))"""
>>> timeit.timeit(code, number=1_000_000)
0.10481472999890684
Now try to timeit the function itself:
>>> timeit.timeit(lambda : Ackermann(6, 4), number=1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/timeit.py", line 232, in timeit
return Timer(stmt, setup, timer, globals).timeit(number)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/timeit.py", line 176, in timeit
timing = self.inner(it, self.timer)
File "<timeit-src>", line 6, in inner
File "<stdin>", line 1, in <lambda>
File "<stdin>", line 8, in Ackermann
File "<stdin>", line 8, in Ackermann
File "<stdin>", line 8, in Ackermann
[Previous line repeated 1 more time]
File "<stdin>", line 6, in Ackermann
File "<stdin>", line 8, in Ackermann
File "<stdin>", line 6, in Ackermann
File "<stdin>", line 8, in Ackermann
File "<stdin>", line 8, in Ackermann
File "<stdin>", line 8, in Ackermann
[Previous line repeated 983 more times]
File "<stdin>", line 6, in Ackermann
File "<stdin>", line 2, in Ackermann
RecursionError: maximum recursion depth exceeded in comparison
See - you can't even run that! Actually, probably nobody can since it's so much recursion!
Why did the first call succeed, though? Because it didn't execute anything, it just spit out a lot of new functions and got rid of all of them shortly after.

Best Python Input method for Integers

In python 2.7, if we take an integer as input, which one is more faster and efficient or there is no difference at all:
input() or int(raw_input())
From the Python docs
input([prompt])
Equivalent to eval(raw_input(prompt)).
This function does not catch user errors. If the input is not syntactically valid, a SyntaxError will be raised. Other exceptions may be raised if there is an error during evaluation.
If the readline module was loaded, then input() will use it to provide elaborate line editing and history features.
Consider using the raw_input() function for general input from users.
int(raw_input()) will be faster, more secure and produce less confusing results.
Consider:
>>> b = 5
>>> a = input()
[1, 2, 3]
>>> a + b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "int") to list
>>> a = int(raw_input())
[1, 2, 3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '[1, 2, 3]'
The ValueError raised when reading input is far more desirable than the TypeError raised when using the variable.

Categories

Resources