Variable changing by itself inside loop - python

I have a python for loop that seems to have a variable changing of its own accord inside the loop. My variables are defined as:
yhat = np.empty((1,len(prices)))
yhat[:] = nan
yhat = yhat.astype('float')
e = Q = yhat
P = R = np.matrix(np.zeros((2,2)))
B = np.empty((2,len(prices)))
B[:] = nan
B = np.matrix(B)
B[:,0] = 0
The loop is: (prices is a dataframe)
for t in xrange(0,len(prices),1):
if t > 0:
B[:,t] = B[:,t-1]
R = P+Vw
yhat[0,t] = x[t,:]*B[:,t]
print yhat[0,t]
Q[0,t] = x[t,:]*R*x[t,:].T + Ve
print yhat[0,t]
e[0,t] = y[t,0] - yhat[0,t]
print yhat[0,t]
K = (R*x[t,:].T)/Q[0,t]
B[:,t] = B[:,t]+K*e[0,t]
P = R - K*x[t,:]*R
I'm printing yhat because I've narrowed the anomaly in the code down to it. After set the value of yhat # t, it seems to change. When I run the code, it prints out:
0.0
0.001
20.438747
Additionally, I'm concerned about the subtraction for e[0,t] because for some reason the subtraction results in the value of yhat at that current moment?
Maybe I'm missing something blatantly obvious. I'm relatively new to python, and I switched over from MATLAB.
EDIT: x & y are also matrix objects. So all of the multiplications are matrix dot products.

e = Q = yhat won't create copies. They are instead additional references to the same object. Altering that object through either the e or Q names will reflect in those changes being visible through the yhat reference too.
So
yhat[0,t] = x[t,:]*B[:,t]
and
Q[0,t] = x[t,:]*R*x[t,:].T + Ve
and
e[0,t] = y[t,0] - yhat[0,t]
all operate on the same, single numpy array object, not on separate objects.
Use the numpy.copy() function to create independent new copies instead:
e, Q = np.copy(yhat), np.copy(yhat)

Related

Python blender API assigns material to only the first 10 objects within loop

In a loop, I'm generating a number of spheres, and assigning a material and a subsurf modifier to them:
for i in range(100):
x = coords[i,0]
y = coords[i,1]
z = coords[i,2]
type = types[i]
bpy.ops.mesh.primitive_uv_sphere_add(location=(x,y,z),radius=0.5)
bpy.data.objects[i].name = f"{i}_{type}"
m = bpy.data.objects[i].modifiers.new('subdiv','SUBSURF')
m.levels = 0
m.render_levels = 2
m.quality = 3
if type == 0:
mat = type_0_mat
else:
mat = type_1_mat
if bpy.data.objects[i].data.materials:
bpy.data.objects[i].data.materials[0] = mat
else:
bpy.data.objects[i].data.materials.append(mat)
However, this assigns the material and modifier to only the first 10 of the generated spheres. I have also noticed, after creating the spheres, that the indices and the names don't end up matching. For instance:
>>> bpy.data.objects[10]
bpy.data.objects['19_0.0']
I would have expected the 10th element to be 9_0.0. What is going on here? Why are the indices jumbled, and is this why only a few get elements assigned to them?

looping gives me the same set of matrices

Hello so I am trying to run this code where i want X_Matrices dictionary to contain all the X_matrix_i matricies. However, all i am getting that X_Matrices end up being the final X_matrix_i of the final loop. I am not quite sure where i am stuck. Any information would be appreciated! thanks.
n = 5
T = 3
p = 5
X_matrix_i = np.zeros((T,p))
X_Matrices = {}
for i in range(n):
X_Matrices["X" + str(i)] = np.zeros((T,p))
for i in range(n):
for t in range(T):
#initial randomness for loop t
ϵ = np.random.normal(0,1,1)
η = np.random.normal(0,1,1)
Covu = np.zeros((p,p))
#Generating X and e of X
for j in range(len(Covu[0])): #covariance matrix for vector x
for l in range(len(Covu)):
Covu[l,j] = 0.7**(np.abs(l-j))
Zerop = np.zeros(p) # mean vector for vector x
x = np.random.multivariate_normal(Zerop,Covu)
X_matrix_i[t] = x
X_Matrices["X" + str(i)] = X_matrix_i
There are two problems here. First one is the conflicting "i" variables in for loops.
One of them should be changed! I replaced the first for loop i variable with k.
for k in range(n):
for t in range(T):
#initial randomness for loop t
The second problem is that by doing
X_Matrices["X" + str(i)] = X_matrix_i
(last line) you are referencing X_Matrices["X" + str(i)] to X_matrix_i! The issue with mutable objects in Python happens! Instead of doing so, you should use shallow copy to assign values to X_Matrices["X" + str(i)]. So a copy of X_matrix_i will be assigned, not X_matrix_i itself.
I replaced the last line with
X_Matrices["X" + str(k)][:] = X_matrix_i
and the problem solved.
[:] acts as shallow copy here.
I think your problem is caused by the redeclaration of i in the second for loop
for j in range(len(Covu[0])): #covariance matrix for vector x
for i in range(len(Covu)):
Covu[i,j] = 0.7**(np.abs(i-j))
Try to rename the i to something else and it should solve your problem.

Convert numpy int to matlab int

I'm calling a matlab function in python through matlab engine, and I'm having problems to pass the variables.
I have figured out how to pass some, but for this on I'm getting an error. should be a scalar int.
but when I pass it I got the error:
File
"C:\ProgramData\Anaconda3\lib\site-packages\matlab_internal\mlarray_utils.py",
line 90, in _normalize_size
if init_dims[0] == 0:
IndexError: tuple index out of range
The code works fine If I do not pass the modn variable, so I know that my problem is the conversion type to matlab of this variable.
this is the python code:
import numpy as np
import matlab
import matlab.engine
eng = matlab.engine.start_matlab()
eng.cd()
Nn = 30
x= 250*np.ones((1,Nn))
y= 100*np.ones((1,Nn))
z = 32.0
xx = matlab.double(x.tolist())
yy = matlab.double(y.tolist())
f=np.arange(start=0.1,stop=0.66,step=0.1)
modnv=np.concatenate((np.ones((Nn)),2*np.ones((Nn))))
count = 0
for fks in f:
fks=np.float(0)
modn = modnv[count]
modn = modn.astype(int)
modn = matlab.int8(modn)
Output = eng.simple_test(xx,yy,z,fks,modn,nargout=4)
A = np.array(Output[0]).astype(float)
B = np.array(Output[1]).astype(float)
C = np.array(Output[2]).astype(float)
D = np.array(Output[3]).astype(float)
count = count + 1
and this is the matlab function simple_test:
function [A,B,C,D] = simple_test(x,y,z,fks,modn)
if modn == 1
A = 3*x+2*y;
B = x*ones(length(x),length(x));
C = ones(z);
D = x*y';
else
A = 3*fks;
B = 3*x+2*y;
C = A+B;
D = x*y'
end
Does someone know how to overcome that?
Whenever you get IndexError: tuple index out of range error its mostly:
Probably one of the indexes is wrong.I suspect you mean to say [0] where you say [1] and [1] where you say [2]. Indexes are 0-based in Python.
you are passing an array to a function that was expecting a variadic sequence of arguments (eg '{}{}'.format([1,2]) vs '{}{}'.format(*[1,2])

Solving multivariate equation for a subset of variables

I am using sympy to solve some equations and I am running into a problem. I have this issue with many equations but I will illustrate with an example. I have an equation with multiple variables and I want to solve this equation in terms of all variables but one is excluded. For instance the equation 0 = 2^n*(2-a) - b + 1. Here there are three variables a, b and n. I want to get the values for a and b not in terms of n so the a and b may not contain n.
2^n*(2-a) - b + 1 = 0
# Since we don't want to solve in terms of n we know that (2 - a)
# has to be zero and -b + 1 has to be zero.
2 - a = 0
a = 2
-b + 1 = 0
b = 1
I want sympy to do this. Maybe I'm just not looking at the right documentation but I have found no way to do this. When I use solve and instruct it to solve for symbols a and b sympy returns to me a single solution where a is defined in terms of n and b. I assume this means I am free to choose b and n, However I don't want to fix n to a specific value I want n to still be a variable.
Code:
import sympy
n = sympy.var("n", integer = True)
a = sympy.var("a")
b = sympy.var("b")
f = 2**n*(2-a) - b + 1
solutions = sympy.solve(f, [a,b], dict = True)
# this will return: "[{a: 2**(-n)*(2**(n + 1) - b + 1)}]".
# A single solution where b and n are free variables.
# However this means I have to choose an n I don't want
# to that I want it to hold for any n.
I really hope someone can help me. I have been searching google for hours now...
Ok, here's what I came up with. This seems to solve the type of equations you're looking for. I've provided some tests as well. Of course, this code is rough and can be easily caused to fail, so i'd take it more as a starting point than a complete solution
import sympy
n = sympy.Symbol('n')
a = sympy.Symbol('a')
b = sympy.Symbol('b')
c = sympy.Symbol('c')
d = sympy.Symbol('d')
e = sympy.Symbol('e')
f = sympy.sympify(2**n*(2-a) - b + 1)
g = sympy.sympify(2**n*(2-a) -2**(n-1)*(c+5) - b + 1)
h = sympy.sympify(2**n*(2-a) -2**(n-1)*(e-1) +(c-3)*9**n - b + 1)
i = sympy.sympify(2**n*(2-a) -2**(n-1)*(e+4) +(c-3)*9**n - b + 1 + (d+2)*9**(n+2))
def rewrite(expr):
if expr.is_Add:
return sympy.Add(*[rewrite(f) for f in expr.args])
if expr.is_Mul:
return sympy.Mul(*[rewrite(f) for f in expr.args])
if expr.is_Pow:
if expr.args[0].is_Number:
if expr.args[1].is_Symbol:
return expr
elif expr.args[1].is_Add:
base = expr.args[0]
power = sympy.solve(expr.args[1])
sym = expr.args[1].free_symbols.pop()
return sympy.Mul(sympy.Pow(base,-power[0]), sympy.Pow(base,sym))
else:
return expr
else:
return expr
else:
return expr
def my_solve(expr):
if not expr.is_Add:
return None
consts_list = []
equations_list = []
for arg in expr.args:
if not sympy.Symbol('n') in arg.free_symbols:
consts_list.append(arg)
elif arg.is_Mul:
coeff_list = []
for nested_arg in arg.args:
if not sympy.Symbol('n') in nested_arg.free_symbols:
coeff_list.append(nested_arg)
equations_list.append(sympy.Mul(*coeff_list))
equations_list.append(sympy.Add(*consts_list))
results = {}
for eq in equations_list:
var_name = eq.free_symbols.pop()
val = sympy.solve(eq)[0]
results[var_name] = val
return results
print(my_solve(rewrite(f)))
print(my_solve(rewrite(g)))
print(my_solve(rewrite(h)))
print(my_solve(rewrite(i)))

For loop Python- from Matlab

I am starting to code up in Python and I come from a Matlab background. I have a problem with a for loop that I am trying to do.
So this is my for loop from Matlab,
ix = indoor(1);
idx = indoor(2)-indoor(1);
%Initialize X apply I.C
X = [ix;idx];
for k=(1:1:287)
X(:,k+1) = Abest*X(:,k) + Bbest*outdoor(k+1) + B1best* (cbest4/cbest1);
end
In this code Abest is a 2x2 matrix, Bbest is a 2x1 matrix, outdoor is a 288x1 vector, B1best is a 2x1 matrix. The matricies are found from a function using the matrix expodential command. c4 and c1 are terms defined before, constants.
In Python I have been able to get the matrix exponential command to work in my function but I can't get that for loop to work.
Xo = np.array([[ix],[idx]])
num1 = range(0,276)
for k in num1:
Xo[:,k+1] = Ae*Xo[:,k] + Be*outdoor[k+1] + Be1*(c4/c1)
Again Ae,Be,Be1 are matrices of the same size just like the Matlab ones. Same thing for the outdoor vector.
I have tried everything I can think of to make it work... The only thing that worked for me was,
Xo = np.zeros(())
#Initial COnditions
ix = np.array(indoor[0])
idx = np.array(indoor[1]-indoor[0])
Xo = np.array([[ix],[idx]])
#Range for the for loop
num1 = range(0,1)
for k in num1:
Xo = Ae*Xo[k] + Be*outdoor[k+1] + Be1*(c4/c1)
Now, this thing will work but only give me two points. If I change the range I get an error. I'm assuming this code works because my original Xo is just two states so k goes through those two states but that's not what I want.
If anyone could help me out that would be very helpful! If I'm making some code error, it's honestly because I'm not understanding the 'For loop' in python to well when it comes to data analysis and having it loop through the rows and increment the columns. Thank you for your time.
Upon Request here is my full code:
import scipy.io as sc
import math as m
import numpy as np
import matplotlib.pyplot as plt
import sys
from scipy.linalg import expm, sinm, cosm
import pandas as pd
df = pd.read_excel('datatemp.xlsx')
outdoor = np.array(df[['Outdoor']])
indoor = np.array(df[['Indoor']])
###########################. FUNCTION DEFINE. #################################################
#Progress bar
def progress(count, total, status=''):
percents = round(100.0 * count / float(total), 1)
sys.stdout.write(' %s%s ...%s\r' % ( percents, '%', status))
sys.stdout.flush()
#Define Matrix for Model
def Matrixbuild(c1,c2,c3):
A = np.array([[0,1],[-c3/c1,-c2/c1]])
B = np.array([[0],[1/c1]])
B1 = np.array([[1],[0]])
C = np.zeros((2,2))
D = np.zeros((2,2))
F = np.array([[0,1,0,1],[-c3/c1,-c2/c1,1/c1,0],[0,0,0,0],[0,0,0,0]])
R = np.array(expm(F))
Ae = np.array([[R.item(0),R.item(1)],[R.item(4),R.item(5)]])
Be = np.array([[R.item(2)],[R.item(6)]])
Be1 = np.array([[R.item(3)],[R.item(7)]])
return Ae,Be,Be1;
###########################. Data. #################################################
#USED FOR JUST TRYING WITHOUT ACTUAL DATA
# outdoor = np.array([5.8115,4.394,5.094,5.1123,5.1224])
# indoor = np.array([15.595,15.2429,15.0867,14.9982,14.8993])
###########################. Model Define. #################################################
Xo = np.zeros((2,288))
ix = np.array(indoor[0])
idx = np.array(indoor[1])
err_min = m.inf
c1spam = np.linspace(0.05,0.001,30)
c2spam = np.linspace(6.2,6.5,30)
c3spam = np.linspace(7.1,7.45,30)
totalspam = len(c1spam)*len(c2spam)*len(c3spam)
ind = 0
for c1 in c1spam:
for c2 in c2spam:
for c3 in c3spam:
c4 = 1.1
#MatrixBuild Function
result = Matrixbuild(c1,c2,c3)
Ae,Be,Be1 = result
Xo = np.array([ix,idx])
Datarange = range(0,len(outdoor)-1,1)
for k in Datarange:
Xo[:,k+1] = np.matmul(Ae,Xo[:,k]) + np.matmul(Be,outdoor[k+1]) + Be1*(c4/c1)
ind = ind + 1
print(Xo)
err = np.linalg.norm(Xo[0,range(0,287)]-indoor.T)
if err<err_min:
err_min = err
cbest = np.array([[c1],[c2],[c3],[c4]])
progress(ind,totalspam,status='Done')
# print(X)
# print(err)
# print(cbest)
###########################. Model with Cbest Values. #################################################
c1 = cbest[0]
c2 = cbest[1]
c3 = cbest[2]
result2 = Matrixbuild(c1,c2,c3)
AeBest,BeBest,Be1Best = result2
Xo = np.array([ix,idx])
Datarange = np.arange(0,len(outdoor)-1)
for k in Datarange:
Xo[:,k+1] = np.matmul(AeBestb,Xo[:,k]) + np.matmul(BeBest,outdoor[k+1]) + Be1Best*(c4/c1)
err = np.linalg.norm(Xo[0,range(0,287)]-indoor.T)
print(cbest)
print(err)
###########################. Plots. #################################################
plt.figure(0)
time = np.linspace(1,2,2)
plt.scatter(time,X[0],s=15,c="blue")
plt.scatter(time,indoor[0:2],s=15,c="red")
plt.show()
And again my error occurs in the line with the for loop of
for k in Datarange:
Xo[:,k+1] = np.matmul(Ae,Xo[k]) + np.matmul(Be,outdoor[k+1]) + Be1*(c4/c1)
I was trying to use np.matmul for matrix multiplication but even without it, it wasn't working.
If there are any other questions about my code please ask. Essentially I'm trying to find the best c1,c2,c3 coefficients that fit my data which is indoor temperature by using a basic second order constant coefficient model.
Have you tried with Xo[:,k+1] instead of Xo(:,k+1)? Python uses [] for slicing and indexing.
EDIT:
Xo = np.array([[ix],[idx]])
This creates a 1x1 array with 1 value: (ix, idx). I think you're looking for something like Xo = np.zeros((ix, idx)), which will give you an ixxidx array initialized to zeros. If you don't need the zeros you can use Xo = np.empty((ix, idx)).
See the docs on array creation.
So by reading into how python works a little more and allocation for arrays/matrices, I was able to find out how to do it. I needed to first allocate my 'Xo' value and then input the initial conditions in order for the For loop to work.
Xo = np.zeros((2,num2))
Xo = np.asmatrix(Xo)
Xo[0,0] = ix
Xo[1,0] = idx
Also for the 'for loop', I called the range some value like this,
num1 = range(0,4)
num2 = len(num1) + 1
This helped in order to calculate the total dimension of 'Xo', by calling it 'num2'. It was also defined like that because my 'For loop' went (k+1), this the dimension would grow larger, ex:
for k in num1:
Xo[:,k+1] = Ae*Xo[:,k] + Be*outdoor[k+1] + Be1*(c4/c1)
But there it is! I figured it by comparing Matlab printouts to Python printouts and just trying to debug one line at a time. Now I have the same exact value print out in both goods, so it is time to start using the python code!

Categories