I am implementing a MCMC simulation for the first time and I have a variable that is defined based on the result of a previous variable. For instance if my bernoulli variable returns a 0, there will be a different value that gets fed into a deterministic variable than if it returns a 1.
with pm.Model() as model:
x = pm.Bernoulli('x', .5)
if x == 1:
y = 1
elif x == 0:
y = 2
z = pm.Deterministic('z', y * 1000)
My issue is that neither of these if statements will get entered because x is not an integer, it is a distribution. Is there a way to get the sampled values of x? Or am I just thinking about this wrong?
You are right, you should use Theano's function switch
with pm.Model() as model:
x = pm.Bernoulli('x', .5)
y = pm.math.switch(x, 1, 0)
z = pm.Deterministic('z', y * 1000)
or a little bit more verbose
with pm.Model() as model:
x = pm.Bernoulli('x', .5)
y = pm.math.switch(pm.math.eq(x, 1), 1, 0)
z = pm.Deterministic('z', y * 1000)
switch evaluates the first argument, if true returns the second argument, otherwise the third one.
You can also use more than one switch if you have more than two conditions.
with pm.Model() as model:
x = pm.DiscreteUniform('x', 0, 2)
y_ = pm.math.switch(pm.math.eq(x, 1), 1, 0)
y = pm.math.switch(pm.math.eq(x, 2), 2, y_)
z = pm.Deterministic('z', y * 1000)
Related
I was trying to write a program which plots level set for any given function.
rmin = -5.0
rmax = 5.0
c = 4.0
x = np.arange(rmin,rmax,0.1)
y = np.arange(rmin,rmax,0.1)
x,y = np.meshgrid(x,y)
f = lambda x,y: y**2.0 - 4*x
realplots = []
for i in range(x.shape[0]):
for j in range(x.shape[1]):
if abs(f(x[i,j],y[i,j])-c)< 1e-4:
realplots.append([x[i,j],y[i,j]])`
But it being a nested for loop, is taking lot of time. Any help in vectorizing the above code/new method of plotting level set is highly appreciated.(Note: The function 'f' will be changed at the time of running.So, the vectorization must be done without considering the function's properties)
I tried vectorizing through
ans = np.where(abs(f(x,y)-c)<1e-4,np.array([x,y]),[0,0])
but it was giving me operands could not be broadcast together with shapes (100,100) (2,100,100) (2,)
I was adding [0,0] as an escape from else condition in np.where which is indeed wrong.
Since you get the values rather than the indexes, you don't really need np.where.
You can directly use the mask to index x and y, look at the "Boolean array indexing" section of the documentation.
It is straightforward:
def vectorized(x, y, c, f, threshold):
mask = np.abs(f(x, y) - c) < threshold
x, y = x[mask], y[mask]
return np.stack([x, y], axis=-1)
Your function for reference:
def op(x, y, c, f, threshold):
res = []
for i in range(x.shape[0]):
for j in range(x.shape[1]):
if abs(f(x[i, j], y[i, j]) - c) < threshold:
res.append([x[i, j], y[i, j]])
return res
Tests:
rmin, rmax = -5.0, +5.0
c = 4.0
threshold = 1e-4
x = np.arange(rmin, rmax, 0.1)
y = np.arange(rmin, rmax, 0.1)
x, y = np.meshgrid(x, y)
f = lambda x, y: y**2 - 4 * x
res_op = op(x, y, c, f, threshold)
res_vec = vectorized(x, y, c, f, threshold)
assert np.allclose(res_op, res_vec)
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.
I want to solve this equation without any Modules(NumPy, Sympy... etc.)
Px + Qy = W
(ex. 5x + 6y = 55)
Thanks.
It is a very crude way to do this, but you can use brute-force technique, as I said in comment under your question. It can probably be optimized a lot, gives only int outputs, but overall shows the method:
import numpy as np
# Provide the equation:
print("Provide a, b and c to evaluate in equation of form {ax + by - c = 0}")
a = float(input("a: "))
b = float(input("b: "))
c = float(input("c: "))
x_range = int(input("x-searching range (-a, a): "))
y_range = int(input("y-searching range (-b, b): "))
error = float(input("maximum accepted error from the exact solution: "))
x_range = np.arange(-x_range, x_range, 1)
y_range = np.arange(-y_range, y_range, 1)
for x in x_range:
for y in y_range:
if -error <= a * x + b * y - c <= error:
print("Got an absolute error of {} or less with numbers x = {} and y = {}.".format(error, x, y))
Example output for a = 1, b = 2, c = 3, x_range = 10, y_range = 10, error = 0.001:
Got an error of 0.001 or less with numbers x = -9 and y = 6.
Got an error of 0.001 or less with numbers x = -7 and y = 5.
Got an error of 0.001 or less with numbers x = -5 and y = 4.
Got an error of 0.001 or less with numbers x = -3 and y = 3.
Got an error of 0.001 or less with numbers x = -1 and y = 2.
Got an error of 0.001 or less with numbers x = 1 and y = 1.
Got an error of 0.001 or less with numbers x = 3 and y = 0.
Got an error of 0.001 or less with numbers x = 5 and y = -1.
Got an error of 0.001 or less with numbers x = 7 and y = -2.
Got an error of 0.001 or less with numbers x = 9 and y = -3.
I am using numpy, but not a built-in function to solve the equation itself, just to create an array. This can be done without it, of course.
There are thousands of ways to solve an equation with python.
One of those is:
def myfunc (x=None, y=None):
return ((55-6*y)/5.0) if y else ((55-5*x)/6.0)
print(myfunc(x=10)) # OUTPUT: 0.833333333333, y value for x == 10
print(myfunc(y=42)) # OUTPUT: -39.4, x value for y == 42
You simply define inside a function the steps required to solve the equation.
In our example, if we have y value we subtract 6*y to 55 then we divide by 5.0 (we add .0 to have a float as result), otherwise (means we have x) we subtract 5*x from 55 and then we divide by 6.0
with the same principle, you can generalize:
def myfunc (x=None, y=None, P=None, Q=None, W=None):
if not W:
return P*x + Q*y
elif not x:
return (W-Q*y)/float(P)
elif not y:
return (W-P*x)/float(Q)
elif not P:
return (W-Q*y)/float(x)
elif not Q:
return (W-P*x)/float(y)
print(myfunc(x=10, P=5, Q=6, W=55)) # OUTPUT: 0.833333333333, y value for x == 10
print(myfunc(y=42, P=5, Q=6, W=55)) # OUTPUT: -39.4, x value for y == 42
check this QA for some other interesting ways to approach this problem
I have the following code that solves simultaneous linear equations by starting with the first equation and finding y when x=0, then putting that y into the second equation and finding x, then putting that x back into the first equation etc...
Obviously, this has the potential to reach infinity, so if it reaches +-inf then it swaps the order of the equations so the spiral/ladder goes the other way.
This seems to work, tho I'm not such a good mathematician that I can prove it will always work beyond a hunch, and of course some lines never meet (I know how to use matrices and linear algebra to check straight off whether they will never meet, but I'm not so interested in that atm).
Is there a better way to 'spiral' in on the answer? I'm not interested in using math functions or numpy for the whole solution - I want to be able to code the solution. I don't mind using libraries to improve the performance, for instance using some sort of statistical method.
This may be a very naive question from either a coding or maths point of view, but if so I'd like to know why!
My code is as follows:
# A python program to solve 2d simultaneous equations
# by iterating over coefficients in spirals
import numpy as np
def Input(coeff_or_constant, var, lower, upper):
val = int(input("Let the {} {} be a number between {} and {}: ".format(coeff_or_constant, var, lower, upper)))
if val >= lower and val <= upper :
return val
else:
print("Invalid input")
exit(0)
def Equation(equation_array):
a = Input("coefficient", "a", 0, 10)
b = Input("coefficient", "b", 0, 10)
c = Input("constant", "c", 0, 10)
equation_list = [a, b, c]
equation_array.append(equation_list)
return equation_array
def Stringify_Equations(equation_array):
A = str(equation_array[0][0])
B = str(equation_array[0][1])
C = str(equation_array[0][2])
D = str(equation_array[1][0])
E = str(equation_array[1][1])
F = str(equation_array[1][2])
eq1 = str(A + "y = " + B + "x + " + C)
eq2 = str(D + "y = " + E + "x + " + F)
print(eq1)
print(eq2)
def Spiral(equation_array):
a = equation_array[0][0]
b = equation_array[0][1]
c = equation_array[0][2]
d = equation_array[1][0]
e = equation_array[1][1]
f = equation_array[1][2]
# start at y when x = 0
x = 0
infinity_flag = False
count = 0
coords = []
coords.append([0, 0])
coords.append([1, 1])
# solve equation 2 for x when y = START
while not (coords[0][0] == coords[1][0]):
try:
y = ( ( b * x ) + c ) / a
except:
y = 0
print(y)
try:
x = ( ( d * y ) - f ) / e
except:
x = 0
if x >= 100000 or x <= -100000:
count = count + 1
if count >= 100000:
print("It\'s looking like these linear equations don\'t intersect!")
break
print(x)
new_coords = [x, y]
coords.append(new_coords)
coords.pop(0)
if not ((x == float("inf") or x == float("-inf")) and (y == float("inf") or y == float("-inf"))):
pass
else:
infinity_flag if False else True
if infinity_flag == False:
# if the spiral is divergent this switches the equations around so it converges
# the infinity_flag is to check if both spirals returned infinity meaning the lines do not intersect
# I think this would mostly work for linear equations, but for other kinds of equations it might not
x = 0
a = equation_array[1][0]
b = equation_array[1][1]
c = equation_array[1][2]
d = equation_array[0][0]
e = equation_array[0][1]
f = equation_array[0][2]
infinity_flag = False
else:
print("These linear equations do not intersect")
break
y = round(y, 3)
x = round(x, 3)
print(x, y)
equation_array = []
print("Specify coefficients a and b, and a constant c for equation 1")
equations = Equation(equation_array)
print("Specify coefficients a and b, and a constant c for equation 1")
equations = Equation(equation_array)
print(equation_array)
Stringify_Equations(equation_array)
Spiral(equation_array)
Can you please tell, how can I pass various differentiable function to T.grad? I want something like this:
x = T.dscalar('x')
ellipic_paraboloid = x ** 2 + y ** 2
hyperbolic_paraboloid = x ** 2 - y ** 2
gradients = theano.function([function_of_xy, x, y], T.grad(function_of_xy, gx, gy))
gradients(ellipic_paraboloid, 1, 1)
gradients(hyperbolic_paraboloid, 1, 1)