Understanding quantifiers in z3 - python

I'm trying to understand this example:
solve([y == x + 1, ForAll([y], Implies(y <= 0, x < y))])
but after reading the explanation I still don't understand it.
How do you read this?
what is the meaning of []?
My wrong interpretation of this is.
"Given the theorem y == x + 1. Does it hold for all y such that Implies(y <= 0, x < y)?"
With this interpretation if I use y = 0 and x = -1 every constraint (Implies(y <= 0, x < y) is true since y <= 0 and x < y) is respected, but If I run this I find out that it's not solvable.
Do you have any hits to how to understand this topic?

Looks like there're a couple of confusions here. Let's first sort out binding: In a quantifier context, the variable is independent, i.e., it can be renamed with no change to the semantics. So, your original:
from z3 import *
x, y = Ints('x y')
solve([y == x + 1, ForAll([y], Implies(y <= 0, x < y))])
is exactly equivalent to:
from z3 import *
x, y, z = Ints('x y z')
solve([y == x + 1, ForAll([z], Implies(z <= 0, x < z))])
Note that we replaced the y in the "scope" of ForAll to z, but left the one in the first conjunct untouched. You can only rename within the scope of ForAll (or Exist), not outside of it.
And both of these equivalent expressions are unsatisfiable. Why? The first conjunct is easy to satisfy; just pick an arbitrary x, and set y to be x+1 and you're done. It's the second conjunct that's unsatisfiable. Because, no matter which x you choose to satisfy the first, you can always find a z that's less than that x (just pick min(0, x-1)), and the quantified formula becomes False for that assignment. And hence there are no solutions.
Now, let's consider the variant you had in your comments, with x > z:
from z3 import *
x, y, z = Ints('x y z')
solve([y == x + 1, ForAll([z], Implies(z <= 0, x > z))])
Again, the first conjunct is easy to satisfy. And this time, so is the second, because you can pick a positive x, and that will be greater than all z's so long as z <= 0, and thus the implication is always true. And that's exactly what z3 is telling you, when it gives you the satisfying assignment:
[x = 2, y = 3]
Note that there's nothing in this assignment regarding the variable z. You cannot really give a model for a universally quantified formula; by definition it is true for all values of z.
Hope this clears things up.

[] is a Python list; the outer one is a list of constraints (representing a conjunction) and the one in the ForAll is a list of constants to bind.
Note that the same constant name can be re-used. In this case, y in y == x + 1 is a global existential and the y in the ForAll is a universally bound variable which also has the name y.

Related

form the largest number possible in a list [duplicate]

This question already has answers here:
Sort a list to form the largest possible number
(9 answers)
Closed 4 years ago.
Given a list such as:
[3, 30, 34, 5, 9].
Output: 9534330
Write a program to return the largest number possible
In my code I have used permutation here:
from itertools import permutations
x = [3, 30, 34, 5, 9]
y = permutations(x)
n = len(y)
e = []
for i in y:
a = map(str, i)
e.append(int("".join(i)))
print "Largest Number {}".format(sorted(e)[-1])
Here n which is the length of the number of permutations is 120 because of 5!.
Is there a better way to solve this problem?
Sorting all numbers in descending order is the simplest solution that occurs to us. But this doesn’t work.
For example, 548 is greater than 60, but in the output, 60 comes before 548. As a second example, 98 is greater than 9, but 9 comes before 98 in the output.
The solution is to use any comparison based sorting algorithm. Thus, instead of using the default comparison, write a comparison function myCompare() and use it to sort numbers.
Given two numbers X and Y, how should myCompare() decide which number to put first – we compare two numbers XY (Y appended at the end of X) and YX (X appended at the end of Y).
If XY is larger, then, in the output, X should come before Y, else Y should come before X.
For example, let X and Y be 542 and 60. To compare X and Y, we compare 54260 and 60542. Since 60542 is greater than 54260, we put Y first.
Calculating Permutations yield a higher time complexity.
A better solution in python would be:
def largestNumber(A):
maxlen = len(str(max(A)))
if all(v == 0 for v in A):
return '0'
return ''.join(sorted((str(v) for v in A), reverse=True,
key=lambda i: i*(maxlen * 2 // len(i))))
largestNumber([3, 30, 34, 5, 9])
The solution to this problem leads to an interesting transformation that is worth explaining.
Assume we want to know which of XY or YX is larger for given X and Y. Numerically, we want the largest of X.10^y + Y and Y.10^x + X, where the lowercase denote the number of digits of the uppercase variables.
Then with a little math, the comparison
X.10^y + Y < Y.10^x + X
can be rewritten
X / (10^x - 1) < Y / (10^y - 1)
so that XY < YX is certainly a transitive relation and defines a total order. This is very good news because it means that the problem can be reduced to ordinary sorting by using this modified comparison operation.
Now notice that X / (10^x - 1) is a periodic fractional number of the form 0.XXXX..., and to compare 0.XXXX... and 0.YYYY..., it suffices to compare over the longest period. Hence the comparison can work as an ordinary string comparison, except that when the end of the shorter string is reached, we cycle back to the first character.
E.g. 12345 > 12 because 12345 > 12|12|1 and 12105 < 12 because 12105 < 12|12|1.
The comparison function can be described as follows:
def Cmp(X, Y):
l= max(len(X), len(Y))
for i in range(l):
if X[i % len(X)] < Y[i % len(Y)]:
return 1 # X > Y
elif X[i % len(X)] > Y[i % len(Y)]:
return -1 # X < Y
return 0 # X == Y
I don't recommend this particular implementation, which will be slow because of the %.

Function return value of x instead of y

f(x) represents the function of a triangular waveform. In which you input the value x and it returns you the associated y value. However my function returns x every time instead of y. For example f(1) should give 2/pi instead of 1.
def f(x):
y=x
if x in arange(-math.pi,-math.pi/2):
y=(-2/math.pi)*x-2
elif x in arange(-math.pi/2,math.pi/2):
y=(2/math.pi)*x
elif x in arange(math.pi/2,math.pi):
y=(-2/math.pi)*x+2
return y
numpy.arange returns an array of non-consecutive numbers. in operation against it will return True only if the left-hand operand belong to those numbers.
You'd better to use <= / < pair to avoid such problem. In addition to be correct, it also save cost of creating arrays.
def f(x):
y = x
if -math.pi <= x < -math.pi/2:
y = (-2/math.pi)*x-2
elif -math.pi/2 <= x < math.pi/2:
y = (2/math.pi)*x
elif math.pi/2 <= x < math.pi:
y = (-2/math.pi)*x+2
return y
The 'in' keyword only checks if the searched element lies in the list. Here, your list contains only values in the step of 1. Perhaps the value of x is not an integral step. Hence, the corrected function would be:
def f(x):
y=x
if x>-math.pi and x<-math.pi/2:
y=(-2/math.pi)*x-2
elif x>-math.pi/2 and x<math.pi/2:
y=(2/math.pi)*x
elif x>math.pi/2 and x<math.pi:
y=(-2/math.pi)*x+2
return y

Why isn't my variable in a list behaving the way I expect it to?

I'm trying to make a simple animation in Python using pygame where a block moves across the screen. I'm including (what I think are) the relevant parts of the code.
x, y = 1, 1
while True:
rwidth, rheight = 10, 10
left, top = x - (rwidth / 2), y - (rheight / 2)
myRect = left, top, rwidth, rheight
pygame.draw.rect(screen, white, myRect)
position = [x, y]
velocity = [5, 5]
position[0] += velocity[0]
What's happening is the block appears where it is supposed to, but it doesn't move. However, if I replace position[0] += velocity[0] with x += velocity[0], it does exactly what I want. From what I understand,position[0] and x should mean exactly the same thing. Why isn't this working?
They don't mean exactly the same thing at all times. When you do position = [x, y], you set position equal to a list the values x and y have at that moment. position does not "auto-update" its value later when x changes (or vice versa). If you change position[0], you need to also change x yourself (and vice versa), or the two will go out of sync.
The issue you're having is because integers in Python are immutable. Unlike some other objects (e.g. lists) that can be changed in-place with operators like +=, an int instance can never be changed from its current value. When you do something like x += 1 (where x is an int), you really get x = x + 1, which creates a new integer object with the result of the sum, then rebinds x to the new value.
In your code, when you do position = [x, y], you make a list with references to two integers that are also bound to the variables x and y. However, when you do position[0] += velocity[0], the identity between x and position[0] breaks down. When dealing with immutable objects, that statement is equivalent to position[0] = position[0] + velocity[0], which creates a new value and stores it in the list, replacing x. The name x remains bound to the previous value, which is unchanged.
It's because of the fact that you are using the values x and y for drawing the block and not position[0] or position[1]. When you are updating the position values, the variables x and y remain same (see your code). So, for the time being position doesn't serve any purpose in your program except that it groups x and y values.

How can I fix this algorithm?

I am trying to create a function in Python. This function should be able to create a list of whole numbers less than or equal to the number provided. I've created an empty list, a variable called y and a while loop. In this while loop, as long as y <= x, the results of the subsequent equations are appended to the empty list, and y increments by 1. However, when I call this function, I get a list with only one element. How can I fix this?
def fff(x):
numbers = []
y = 2
while(y <= x):
x = x - (x - y)
numbers.append(x)
y += 1
return numbers
>>> fff(10)
[2]
That function already exists, more or less.
Python 2
def fff(x):
return range(1,x+1)
Python 3
def fff(x):
return list(range(1,x+1))
If you look at this line x = x - (x - y) and think of your inputs, you will see the problem. if x initially equals 10, then x - (x - y) equals 2, and y will equal 3, therefore breaking out of your loop.
If you are trying to mimic the range function then this is how you would do it:
def fff(x):
numbers = []
y = 1
while(y <= x):
numbers.append(y)
y += 1
return numbers

Python: for statement behavior

My question concerns the output of this statement:
for x in range(4), y in range(4):
print x
print y
Results in:
[0, 1, 2, 3]
2
True
2
It seems there is a comparison involved, I just can't figure out why the output is structured like this.
My guess is that you're running this from an interactive console, and already had y defined with a value of 2 (otherwise, you'd get NameError: name 'y' is not defined). That would lead to the output you observed.
This is due to for x in range(4), y in range(4): actually being equivalent to the following when evaluated:
for x in (range(4), y in range(4)):
which reduces to...
for x in ([0,1,2,3], 2 in range(4)):
which again reduces to...
for x in ([0,1,2,3], True):
This then results in 2 iterations of the for loop, since it iterates over each element of the tuple:
x = [0,1,2,3]
x = True.
(And of course, y is still 2.)
You've created a weird, weird thing there.
>>> y = 2
>>> range(4), y in range(4)
([0, 1, 2, 3], True)
The y in range(4) is a membership test.
The range(4), y in range(4) is a pair of items; a tuple.
The variable x is set to range(4), then the result of y in range(4).
The variable y is just laying around with a value; it is not set by the for statement.
This only works hacking around on the command line typing random stuff with y left laying around.
This isn't sensible Python code at all.
[And yes, the word in has two meanings. So do ()'s and several other pieces of syntax.]
You seem to have y defined prior to running this code. What you're iterating over is a two-item tuple: first item is range-generated list, second is True, which is result of the y in range(4):
>>> y = 2
>>> for x in range(4), y in range(4):
print x, 'x'
print y, 'y'
[0, 1, 2, 3] x
2 y
True x
2 y
What I suspect you were trying to do is to iterate over two variables from two lists. Use zip for this.
Dav nailed down perfectly why the syntax you wrote doesn't work.
Here are the syntaxes that do work for what you're probably trying to do:
If you want all 4 x 4 combinations for x and y, you want 2 nested loops:
for x in range(4):
for y in range(4):
print x, y
Or if you really want to use one loop:
import itertools
for (x, y) in itertools.product(range(4), range(4)):
print x, y
itertools.product() generates all possible combinations:
This is less readable than 2 loops in this simple case, but the itertools module has many other powerful functions and is worth knowing...
If you want x and y to advance in parallel over two sequences (aka "lock-step" iteration):
for (x, y) in zip(range(4), range(4)):
print x, y
# `zip(range(4), range(4))` is silly since you get x == y;
# would be useful for different sequences, e.g.
# zip(range(4), 'abcd')
[Background: The name zip comes from Haskell; think about how a Zipper takes one tooth from here and one from there:
zip() cuts off to the length of the shortest sequence; the itertools module has other variants...]

Categories

Resources