Python, why you always lying? [duplicate] - python

This question already has answers here:
"is" operator behaves unexpectedly with integers
(11 answers)
Closed 3 years ago.
The community reviewed whether to reopen this question 25 days ago and left it closed:
Original close reason(s) were not resolved
Python seems to be inconsistent.
x = 100
y = 100
x is y
Returns True, yet:
x = 300
y = 300
x is y
Returns False.
I even tried with new, clean variables:
> x = 100
> y = 100
> x is y
True
> x = 300
> y = 300
> x is y
False
> x = 100
> y = 100
> x is y
True
> x2 = 300
> y2 = 300
> x2 is y2
False
> x2
300
> y2
300
> x2 is y2
False
> x2 = 100
> y2 = 100
> x2 is y2
True
What is happening here? Am I confused about the "is" key word?

The is keyword compares whether two things are actually the same object. An easy way to think about this is in terms of memory addresses – that is, x is y is another way of writing id(x) == id(y)
There is no guarantee that two objects assigned to the same value will share the same memory address. Sometimes they will, though. That's all that's going on.
If you wish to compare the variables' values, use the comparison operator:
x == y
Edit: upon doing some research, it seems that python uses the same memory adresses for integers in the range [-5, 256] (this is pretty arbitrary, but there is some reasoning for it: it's just some common negative numbers along with 0 - 255, plus 256 because it's also a common number). That would explain why is returns True for 100 but not 300.
So, 256 is 256 returns True, but 257 is 257 returns False

Related

How do you check if something has declined by 10% without an if statement?

I am given two numbers x and y in Python, and I'm asked if y represents a 10% decrease from x.
What is the best way of doing this without an if-statement? I am looking to vectorize this operation, so it'd be good to have a branchless form.
The verbose check would be:
def check(x,y):
if x < 0:
return y < x*1.1
else:
return y < x*0.9
I considered
def check(x,y):
return y < x * (1.1 if x < 0 else 0.9)
but that's just an inline if-statement.
If I understand the question correctly, I think this should work:
def ten_percent_decrease(x: int, y: int):
"""
check if y is 10% less than x
"""
return (x - y) / abs(x) > 0.1
Note: the code breaks if you give 0 for x. I'm not sure what you want the expected output to be in that case, but you can adjust it accordingly.

inverted indicator constraint in gurobipy

I am a beginner in gurobipy. I would like to add an inverted indicator constraint.
Indicator constraint is nothing but depending on a binary variable a constraint does or does not hold.
In gurobipy this is written as
model.addConstr((x == 1) >> (y + z <= 5))
where x is a binary variable, y and z are integer variables. This statement says that if x is True then the constraint y+z <= 5 holds.
But I would like to have an inverted constraint like this.
If y+z <= 5 then x == 1. But gurobi does not allow the lhs part of the statement to be an inequality. It can only be a binary variable equal to a constant (0 or 1).
So the inverted statement throws an error.
model.addConstr((y + z <= 5) >> (x == 1))
Any ideas how to rewrite such a conditional constraint in gurobipy?!
The implication
y+z ≤ 5 ⇒ x = 1
can be rewritten as:
x = 0 ⇒ y+z ≥ 6
This can be directly implemented as an indicator constraint.
This is based on propositional logic. This is called transposition:
A ⇒ B
⇔
not B ⇒ not A
So in theory we have
y+z ≤ 5 ⇒ x = 1
⇔
x = 0 ⇒ y+z > 5
If x and y are integers we can say x = 0 ⇒ y+z ≥ 6 If they are continuous variables you could do: x = 0 ⇒ y+z ≥ 5.0001 (in practice I would do: x = 0 ⇒ y+z ≥ 5 and keep things ambiguous at y+z = 5).
This is kind of a standard trick when using indicator constraints. It seems not everyone is aware of or appreciates this.
The indicator syntax is
binary expression >> linear constraint
So your constraint is invalid. You need a different model that forces x to 1 when y + z ≤ 5. Assuming y, z are non-negative integers, try 6x + y + z ≥ 6.
I think the best way to go with this one is to use the big-M approach
Let reconsider the problem you are trying to model
If y+z <= 5 then x == 1
It is equivalent to if y+z-5 <= 0 then x==1
From here we need a logic that will turn on and off the variable x depending on the condition on the y+z-5
y + z - 5 <= M(1-x)
will do the trick. Note that the x will need to be 1 for the relationship to hold if y+z-5 <= 0 which is what we want. Similarly, x will be turned off (set to 0) if y+z-5 >= 0
I hope this helps

How can an expression be different from however paarenthesized? [duplicate]

This question already has answers here:
Why does the expression 0 < 0 == 0 return False in Python?
(9 answers)
python operator precedence of in and comparison [duplicate]
(3 answers)
Closed 5 years ago.
Consider this statement:
> False == False in [False]
True
However:
> (False == False) in [False]
False
> False == (False in [False])
False
It is incredible. What's the reason and the interpretation?
dis.dis to the rescue and a bit of my interpretation.
Anyway, it looks like this. Consider three expression X, Y, Z and two operators O1, O2. Then
X O1 Y O2 Z
is equivalent to
(X O1 Y) and (Y O2 Z)
as can be seen by
a < b < c
example. I find this behaviour very counterintuitive.
And the docs:
Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).
Note that in is a comparison operator.

0 is 0 == 0 (#evaluates to True?) [duplicate]

This question already has answers here:
Why does the expression 0 < 0 == 0 return False in Python?
(9 answers)
Closed 6 years ago.
This baffles me. Even without knowing the precedence order, one can check that the two possible ways to gather the expression would give False :
>>> (0 is 0) == 0
False
>>> 0 is (0 == 0)
False
But
>>> 0 is 0 == 0
True
How come?
You are using comparison operator chaining. The expression is interpreted as:
(0 is 0) and (0 == 0)
From the Comparisons documentation:
Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).
0 is 0 is true because Python interns small integers, an implementation detail, so you get (True) and (True) producing True.
When chaining comparison operators in Python, the operators aren't actually applied to the result of the other operators, but are applied to the operands individually. That is x ? y ?? z (where ? and ?? are supposed to stand in for some comparison operators) is neither equivalent to (x ? y) ?? z nor x ? (y ?? z), but rather x ? y and y ?? z.
This is particularly useful for > and co., allowing you to write things like min < x < max and have it do what you want rather than comparing a boolean to a number (which would happen in most other languages).

Simple while loop wont break

I'm completely new to python and coding in general, it's probably some ridiculously obvious error but I can't figure out why this while loop won't break.
I'm trying to find the value of t when y is equal to 0. When changing t manually, y is less than 0 when t is just under 2.5.
Unfortunately I don't have anyone else I can ask for right now. Thanks!
t = 0
y0 = 1.8
v0 = 15.0
theta0 = 0.785398163
vy0 = v0*sin(theta0)
ay0 = -9.81
y = y0 + vy0*t + 0.5*ay0*t**2
while y > 0:
print(t)
t += 0.25
if y < 0:
break
print(t)
You need to include your equation in the loop so that the value of y changes each time you increase t. Like this:
while y > 0:
y = y0 + vy0*t + 0.5*ay0*t**2
print(t)
t += 0.25
if y < 0:
break print(t)
You could restructure your loop as follows:
t = 0
y0 = 1.8
v0 = 15.0
theta0 = 0.785398163
vy0 = v0*sin(theta0)
ay0 = -9.81
y = 1 # dummy start value
while y >= 0:
y = y0 + vy0*t + 0.5*ay0*t**2
print("t={}, y={}".format(t,y))
t += 0.25
This would then also display all of the values as it loops, so you can see it working:
t=0, y=1.8
t=0.25, y=4.145087928395659
t=0.5, y=5.8770508567913184
t=0.75, y=6.9958887851869775
t=1.0, y=7.501601713582638
t=1.25, y=7.394189641978297
t=1.5, y=6.673652570373955
t=1.75, y=5.339990498769618
t=2.0, y=3.3932034271652753
t=2.25, y=0.8332913555609345
t=2.5, y=-2.3397457160434065
By adding a dummy start value, it ensures that the loop will be entered, and avoids the need to also add a break statement within the loop.
From these results you can see there is a solution somewhere between 2.25 and 2.5. You could then change your start value to say t = 2.25 and change the increment to t += 0.01 and you would see a slightly more accurate estimation.
while y > 0
at this line loop will start when y > 0, but then you didn't change the value of y during while loop then how if y < 0 this statement will execute.
And your y = 1.8 after calculating y = y0 + vy0*t + 0.5*ay0*t**2 so it is an infinite loop as y > 0 is all time true.
As you can see from other answers, you need to move your equation to inside the while loop.
In programming the assignment operator (this thing: =) does not create relationships between variables. It (usually) simply takes what is on the right and puts it in what is on the left.
Consider this code:
y = 0
x = y+1
y = 33
print x
It will print out 1.
y+1 gets evaluated to 0+1 then 1.
Then x gets set to the integer value of 1.
Changing y will not do anything because x was set to the specific value of that expression at that specific time, not to a reference.
You might have noticed the "usually" in my definition of the assignment operators, that's because references do exist in programming and specifically in python. For example this happens when you set a variable equal to an uninstantiated class, but at this point understanding that is not necessary.

Categories

Resources