PYTHON 3:UnboundLocalError local variable 'x' referenced before assignment - python-3.x

this code gave this error: UnboundLocalError: local variable 'x' referenced before assignment
def predict_price(location,sqft,bath,BHK):
loc_index = numpy.where(x.columns==location)[0][0]
x = numpy.zeros(len(x.columns))
x[0] = sqft
x[0] = bath
x[0] = BHK
if loc_index >=0:
x[loc_index] = 1
return lr_clf.predict([x])[0]
predict_price("calabar",1000, 2, 2)

The issue is that you are referencing x.columns in the initializer.
x = numpy.zeros(len(x.columns))
In other words, you are defining x based on the length of columns in x. If x is not yet defined, then how is it possible to determine how many columns it has?

Related

Python cvxpy - reuse some constraints

I'm currently using cvxpy to optimize a really big problem but now facing the current issue.
I run multiple iterations of the solver (every iteration reduces the flexibility of some variables).
Every run has 50 constraints in total, of which only 2 of them are different on every run. The remaining 48 constraints are identical.
During every iteration I rebuild from scratch those 2 constraints, the problem, and the obj function.
If I don't rebuild the remaining (same) 48 constraints, the final solution makes no sense.
I read this post CVXPY: how to efficiently solve a series of similar problems but here in my case, I don't need to change parameters and re-optimize.
I just managed to prepare an example that shows this issue:
x = cvx.Variable(3)
y = cvx.Variable(3)
tc = np.array([1.0, 1.0,1.0])
constraints2 = [x >= 2]
constraints3 = [x <= 4]
constraints4 = [y >= 0]
for i in range(2):
if i == 0:
constraints1 = [x - y >= 0]
else:
x = cvx.Variable(3)
y = cvx.Variable(3)
constraints1 = [x + y == 1,
x - y >= 1,
x - y >= 0,
x >= 0]
constraints = constraints1 + constraints2 + constraints3 + constraints4
# Form objective.
obj = cvx.Minimize( (tc.T # x ) - (tc.T # y ) )
# Form and solve problem.
prob = cvx.Problem(obj, constraints)
prob.solve()
solution_value = prob.value
solution = str(prob.status).lower()
print("\n\n** SOLUTION: {} Value: {} ".format(solution, solution_value))
print("* optimal (x + y == 1) dual variable", constraints[0].dual_value)
print("optimal (x - y >= 1) dual variable", constraints[1].dual_value)
print("x - y value:", (x - y).value)
print("x = {}".format(x.value))
print("y = {}".format(y.value))
As you can see, constraints2 requires all the values in the x vector to be greater than 2. constraints2 is added in both iterations to "constraints" that is used in the solver.
The second solution should give you values of vector x that are less than 2.
Why? How to avoid this issue?
Thank you
You need to use parameters as described in the linked post. Suppose you have the constraint rhs >= lhs which is sometimes used and other times not, where rhs and lhs have dimensions m x n. Write the following code:
param = cp.Parameter((m, n))
slack = cp.Variable((m, n))
param_constraint = [rhs >= lhs + cp.multiply(param, slack)]
Now to turn off the constraint, set param.values = np.ones((m, n)). To turn the constraint on, set param.values = np.zeros((m, n)). You can turn some entries of the constraint off/on by setting some entries of param to be 1 and others to be 0.

How are the values being determined in this basic Python class?

I am new to Python and to OOP concept. I was doing a EdX course and came across this code. I have modified it a little bit here. But I need to understand what exactly is happening here.
Question-1: Why does print(baba.x) give 7 but not 3?
Question-2: What does print(X) (capital X) do here? In getX and init I am using 'x' and not 'X'. So where does print(X) get its value from? It seems it is getting this value from the X=7 assignment. But isn't that assignment happening outside of the method getX and also outside of the class Weird. So why is getX able to access X=7 value?
I have searched on scope in Python, but was getting too complicated for me.
class Weird(object):
def __init__(lolo, x, y):
lolo.y = y
lolo.x = x
def getX(baba,x):
print (baba.x)
print (x)
print (X)
X = 7
Y = 8
w1 = Weird(X, Y)
print(w1.getX(3))
The output of the above code is:
7
3
7
None
Read What is the purpose of the word 'self', in Python?
class Weird(object):
def __init__(self, x, y):
self.y = y
self.x = x
def getX(self,x):
print (self.x) # this is the x value of this instance
print (x) # this is the x value you provide as parameter
print (X) # this might read the global X
X = 7
Y = 8
w1 = Weird(X, Y) # this sets w1.x to X (7) and w1.y to Y (8)
print(w1.getX(3)) # this provides 3 as local x param and does some printing

How to put time difference value into summation equation using python

Here I wrote the summation equation to find the Y value according to my csv file.
Here I want to write for range 0 with time difference. When I wrote it gave me this error, ("'str' object cannot be interpreted as an integer", 'occurred at index 0')
my summation equation,
n = time difference in between two rows
my code:
def y_convert(X,time):
Y=0
if x == 10:
for k in range(0,time):
Y=np.sum(X*k)
else:
for k in range(0,time):
Y=np.sum(X*k)
return Y
Then convert time difference into minute and then apply this code to find y
df1['time_diff'] = pd.to_datetime(df1["time"])
df1['delta'] = (df1['time_diff']-df1['time_diff'].shift()).fillna(0)
df1['t'] = df1['delta'].apply(lambda x: x / np.timedelta64(1,'m')).astype('int64') % (24*60)
X = df1['X'].astype(int)
time=df1['t'].astype(int)
Y = df1.apply(lambda x: y_convert(x.X,x.time), axis=1)
Then I tried to plot the graph after getting the correct answer provided by jezrael
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(time, df1['Y'])
ax.set_xlabel
ax.set_ylabel
plt.show()
Plot graph:
my csv file:
I think you need pass column t, not column time:
df1['t'] = df1['delta'].dt.total_seconds().div(60).astype(int)
Y = df1.apply(lambda x: y_convert(x.X,x.t), axis=1)
Reason is if use range function in time, second argument is no time, but integer.
In your solution is used:
range(0,'6:15:00')
Also seems your solution should be simlify a lot:
Y = df1['X'] * (df1['t'] - 1)

how to define the numerical value for objective in gurobi

I am using gurobi and in my object I want to maximize difference between two variables
X1 - X2
But it is not important which variable is bigger so I want to use numerical value of this difference:
|X1 - X2|
How can I define this type of objective in gurobi.
Blow is a semi code of an implementation that I want to do:
m = Model("mip1")
Edges = tuplelist([(1,2),(1,3),(3,4),(3,5),(3,6),(5,6),(6,7),
(8,9),(9,10),(11,12),(12,10),(12,13),(14,10),
])
x = m.addVars(Edges, lb=0.0, ub=1.0, name = "x")
m.setObjectiveN(quicksum(x[w,s] for w,s in Edges),0)
-------my second variables and objective----
y = m.addVars(2, vtype=GRB.BINARY, name="y")
y[0] = quicksum(x.select(1,'*'))
y[1] = quicksum(x.select(8,'*'))
m.setObjectiveN(|y[0]-y[1]|,1)
m.optimize()
Gurobi only accepts absolute values in the constraints, so you could do it like this:
# Define two helper variables
z = m.addVar(name="z")
h = m.addVar(name="h")
m.addConstr(h == y[0]-y[1]) # h = y[0]-y[1]
m.addConstr(z == abs_(h)) # z == |h| == | y[0] - y[1] |
m.setObjectiveN(z, 1) # Maximize z = |h| = |y[0]-y[1]|
where _abs() is a general constraint.

Accessing global variable in function in python

I have two pieces of code:
def g(y):
print(x)
x = 5
g(x)
and
def h(y):
x = x + 1
x = 5
h(x)
The first piece of code works perfectly fine printing '5' while the second piece returns:
UnboundLocalError: local variable 'x' referenced before assignment
What does this actually mean? Is it trying to say that it tried to evaluate the line x = x + 1 before it evaluates the line x=5? If that is so, why has the first piece of code not generated any error? It similarly had to evaluate the line print(x) before x was assigned a value.
I think I might have an misunderstanding how functions are called. But I do not know what it is that I got wrong.
# first block: read of global variable.
def g(y):
print(x)
x = 5
g(x)
# second block: create new variable `x` (not global) and trying to assign new value to it based on on this new var that is not yet initialized.
def h(y):
x = x + 1
x = 5
h(x)
If you want to use global you need to specify that explicitly with global keyword:
def h(y):
global x
x = x + 1
x = 5
h(x)
Just as Aiven said, or you can modify the code like this:
def h(y):
x = 9
x = x + 1
print(x) #local x
x = 5
h(x)
print(x) #global x

Resources