scipy.optimize.minimize, travelling salesman with integer programming - python

import numpy as np;
import math;
import random;
from scipy.optimize import minimize;
def matrixmult (A, B):
rows_A = len(A)
cols_A = len(A[0])
rows_B = len(B)
cols_B = len(B[0])
Z = [[0 for row in range(rows_B)] for col in range(cols_A)]
for i in range(cols_A):
for j in range(rows_A):
#for k in range(cols_A):
Z[i][j] += A[i][j] * B[i][j]
return Z
def constraint1(x):
A=x
rows_X = cols_X = len(x)
ad = np.ones((len(x),1)) #makes a 7x1 array of ones
ad1 = x.sum(axis=1) # makes 7x1 array, each element is sum of each rows
ad2 = np.matrix(ad1)
for i in range(len(x)):
ad[i] = ad[i] - ad2[i] # sum of each row in a binary matrix must be 1 to indicate there is only one entrance or exit for each node
#for j in range(cols_X):
#ad = ad - ad1[i]
return ad
def constraint2(x):
rows_X = cols_X = len(x)
ad3 = np.ones((1,len(x)))
ad4 = x.sum(axis=0)
ad5 = np.matrix(ad4)
for i in range(len(x)):
ad3[i] = ad3[i] - ad5[i]
#for j in range(cols_X):
#ad = ad - ad1[i]
return ad3
def total(C):
C = np.array([[np.nan,3,5,np.nan,np.nan,np.nan,3],[3,np.nan,3,7,np.nan,np.nan,11],[5,3,np.nan,3,np.nan,np.nan,np.nan],[np.nan,7,3,np.nan,3,9,11],[np.nan,np.nan,np.nan,3,np.nan,3,np.nan],[np.nan,np.nan,np.nan,9,3,np.nan,3],[3,11,np.nan,11,np.nan,3,np.nan]])
X = [[0 for row in range(len(C))] for col in range(len(C[0]))]
for i in range(len(C[0])):
for j in range(len(C)):
if math.isnan(C[i][j]) == False :
X[i][j] += random.randint(0,1)
else :
X[i][j]==np.nan
CX = matrixmult (C, X)
cx = np.array(CX)
x = np.matrix(X)
print(x.sum(axis=1))
print(x.sum(axis=0))
print(x)
print(cx)
tot = 0
for i in range(len(cx[0])):
for j in range(len(cx)):
if math.isnan(cx[i][j]) == False :
#print (i,j)
tot += cx[i][j]
#for i in range(len(cx[0])):
#for j in range(len(cx)):
#if math.isnan(cx[i][j]) == False :
#print (i,j)
return tot
C = np.array([[np.nan,3,5,np.nan,np.nan,np.nan,3],[3,np.nan,3,7,np.nan,np.nan,11],[5,3,np.nan,3,np.nan,np.nan,np.nan],[np.nan,7,3,np.nan,3,9,11],[np.nan,np.nan,np.nan,3,np.nan,3,np.nan],[np.nan,np.nan,np.nan,9,3,np.nan,3],[3,11,np.nan,11,np.nan,3,np.nan]])
con1 = {'type' : 'eq', 'fun' : constraint1}
con2 = {'type' : 'eq', 'fun' : constraint2}
cons = [con1,con2]
path = minimize(total, 12,method='SLSQP', jac=None, bounds=None, tol=None, callback=None, constraints = cons)
print(path)
I need to implement traveling salesman problem with linear programming. My intention to use python optimization tools. Its my first program in python and optimization programs.
Since there are two constraints forces traveling salesman to visit(enter and leave) every node once, I wanted to create binary selection 'x' matrix with the same dimensions of cost matrix. Since there is one entrance every column of the selection matrix will sum to 1 and the same for each exit.
I have problems with the usage of scipy.optimize.minimize method. I am not able to send selection matrix to the constraint functions. I will appreciate if anybody helps, thanks in advance.. (sub-tour elimination constraints are not implemented yet)

from cvxpy import *
import numpy as np
import math;
import random;
n = 7
#X = Bool(n , n)
#Y = Bool(n , 1)
#C = np.random.randint(1,5,(n,n))
C = np.array([[np.nan,3,5,np.nan,np.nan,np.nan,3],[3,np.nan,3,7,np.nan,np.nan,11],[5,3,np.nan,3,np.nan,np.nan,np.nan],[np.nan,7,3,np.nan,3,9,11],[np.nan,np.nan,np.nan,3,np.nan,3,np.nan],[np.nan,np.nan,np.nan,9,3,np.nan,3],[3,11,np.nan,11,np.nan,3,np.nan]])
#X = [[0 for row in range(len(C))] for col in range(len(C[0]))]
X = np.zeros((n,n))
for i in range(n):
for j in range(n):
if math.isnan(C[i][j]) == False :
X[i][j] += random.randint(0,1)
else :
X[i][j]== np.nan
#x = np.array(X, dtype = np.float64)
P = C*X
nodes = []
tot = 0
for i in range(n):
for j in range(n):
if math.isnan(P[i][j]) == False :
tot += P[i][j]
if(P[i][j] >0):
print (i,j)
nodes.append((i,j))
print(nodes)
print(len(nodes))
objective = Minimize(tot)
constraints = []
constraints.append( sum_entries( X, axis=0 ) == 1 )
constraints.append( sum_entries( X, axis=1 ) == 1 )
#constraints.append( sum_entries(Y) == C )
prob = Problem(objective, constraints)
prob.solve(solver=GLPK_MI)
print (prob.value)
print(tot)
print(C)
print(X)
print(P)
#print(objective)
Now i have an edited optimization code using cvxpy packet. But it could not minimize the objective. I could not find more examples on cvxpy MILP examples. If you have any suggestion this will be nice. thanks

Related

Heat equation divide by zero issue

I'm writing a code that solves a heat equation implementing an implicit method. The problem is that the values between first and last layer of the matrix are NaNs. What could be the problem?
From my problem of view, the main issue might be with the 105th line, which represents the convrsion of original function to the one that includes the boundary function.
Boundary functions code:
def func(x, t):
return x*(1 - x)*np.exp(-2*t)
# boundary function for x = 0 and x = 1
def q0(t):
return t*np.exp(-t/0.1)*np.cos(t) # граничное условие при x = 0
def q1(t):
return t*np.exp(-t/0.5)*np.cos(t) # граничное уcловие при x = 1
def derivative(f, x0, step):
return (f(x0+step) - f(x0))/step
# boundary function that for t = 0
def u_x0(x):
return (-x + 1)*x
Function that solves the three-diagonal matrix equation
def solution(a, b):
n = len(a)
x = [0 for k in range(0, n)]
# forward
v = [0 for k in range(0, n)]
u = [0 for k in range(0, n)]
# first string (t = 0)
v[0] = a[0][1] / (-a[0][0])
u[0] = ( - b[0]) / (-a[0][0])
for i in range(1, n - 1):
v[i] = a[i][i+1] / ( -a[i][i] - a[i][i-1]*v[i-1] )
u[i] = ( a[i][i-1]*u[i-1] - b[i] ) / ( -a[i][i] - a[i][i-1]*v[i-1] )
# last string (t = 1)
v[n-1] = 0
u[n-1] = (a[n-1][n-2]*u[n-2] - b[n-1]) / (-a[n-1][n-1] - a[n-1][n-2]*v[n-2])
x[n-1] = u[n-1]
for i in range(n-1, 0, -1):
x[i-1] = v[i-1] * x[i] + u[i-1]
return x
Coefficent matrix values:
A = -t/h**2
B = 1 + 2*t/h**2
C = -t/h**2
Code that actually solves the matrix:
i = 1
X =[]
while i < 99:
X = solution(cool_array, f)
k = 0
while k < len(x_i):
#line-105
X[k] += 0.01*(func(x_i[k], x_i[i]) - (1 - x_i[i])*derivative(q0, x_i[i], 0.01) - (x_i[i])*derivative(q1, x_i[i], 0.01))
k+=1
a = 1
while a < 98:
w_h_t[i][a] = X[a]
a+=1
f = X
f[0] = w_h_t[i][0]
f[99] = w_h_t[i][99]
i+=1
print(w_h_t)
As far as I understand, the algorith solution(a, b) is written properly, so I guess the problem might be with the boundary functions or with the 105th line. The output I expect is at least an array of number, not NaNs.

General minimal residual method with right-preconditioner of SSOR

I am trying to implement the algorithm of GMRES with right-preconditioner P for solving the linear system Ax = b . The code is running without error; however, it pops into unprecise result for me because the error I have is very large. For the GMRES method (without preconditioning matrix - remove P in the algorithm), the error I get is around 1e^{-12} and it converges with the same matrix.
import numpy as np
from scipy import sparse
import matplotlib.pyplot as plt
from scipy.linalg import norm as norm
import scipy.sparse as sp
from scipy.sparse import diags
"""The program is to split the matrix into D-diagonal; L: strictly lower matrix; U strictly upper matrix
satisfying: A = D - L - U """
def splitMat(A):
n,m = A.shape
if (n == m):
diagval = np.diag(A)
D = diags(diagval,0).toarray()
L = (-1)*np.tril(A,-1)
U = (-1)*np.triu(A,1)
else:
print("A needs to be a square matrix")
return (L,D,U)
"""Preconditioned Matrix for symmetric successive over-relaxation (SSOR): """
def P_SSOR(A,w):
## Split up matrix A:
L,D,U = splitMat(A)
Comp1 = (D - w*U)
Comp2 = (D - w*L)
Comp1inv = np.linalg.inv(Comp1)
Comp2inv = np.linalg.inv(Comp2)
P = w*(2-w)*np.matmul(Comp1inv, np.matmul(D,Comp2inv))
return P
"""GMRES_SSOR using right preconditioning P:
A - matrix of linear system Ax = b
x0 - initial guess
tol - tolerance
maxit - maximum iteration """
def myGMRES_SSOR(A,x0, b, tol, maxit):
matrixSize = A.shape[0]
e = np.zeros((maxit+1,1))
rr = 1
rstart = 2
X = x0
w = 1.9 ## in ssor
P = P_SSOR(A,w) ### preconditioned matrix
### Starting the GMRES ####
for rs in range(0,rstart+1):
### first check the residual:
if rr<tol:
break
else:
r0 = (b-A.dot(x0))
rho = norm(r0)
e[0] = rho
H = np.zeros((maxit+1,maxit))
Qcol = np.zeros((matrixSize, maxit+1))
Qcol[:,0:1] = r0/rho
for k in range(1, maxit+1):
### Arnodi procedure ##
Qcol[:,k] =np.matmul(np.matmul(A,P), Qcol[:,k-1]) ### This step applies P here:
for j in range(0,k):
H[j,k-1] = np.dot(np.transpose(Qcol[:,k]),Qcol[:,j])
Qcol[:,k] = Qcol[:,k] - (np.dot(H[j,k-1], Qcol[:,j]))
H[k,k-1] =norm(Qcol[:,k])
Qcol[:,k] = Qcol[:,k]/H[k,k-1]
### QR decomposition step ###
n = k
Q = np.zeros((n+1, n))
R = np.zeros((n, n))
R[0, 0] = norm(H[0:n+2, 0])
Q[:, 0] = H[0:n+1, 0] / R[0,0]
for j in range (0, n+1):
t = H[0:n+1, j-1]
for i in range (0, j-1):
R[i, j-1] = np.dot(Q[:, i], t)
t = t - np.dot(R[i, j-1], Q[:, i])
R[j-1, j-1] = norm(t)
Q[:, j-1] = t / R[j-1, j-1]
g = np.dot(np.transpose(Q), e[0:k+1])
Y = np.dot(np.linalg.inv(R), g)
Res= e[0:n] - np.dot(H[0:n, 0:n], Y[0:n])
rr = norm(Res)
#### second check on the residual ###
if rr < tol:
break
#### Updating the solution with the preconditioned matrix ####
X = X + np.matmul(np.matmul(P,Qcol[:, 0:k]), Y) ### This steps applies P here:
return X
######
A = np.random.rand(100,100)
x = np.random.rand(100,1)
b = np.matmul(A,x)
x0 = np.zeros((100,1))
maxit = 100
tol = 0.00001
x = myGMRES_SSOR(A,x0,b,tol,maxit)
res = b - np.matmul(A,x)
print(norm(res))
print("Solution with gmres\n", np.matmul(A,x))
print("---------------------------------------")
print("b matrix:", b)
I hope anyone could help me figure out this!!!
I'm not sure where you got you "Symmetric_successive_over-relaxation" SSOR code from, but it appears to be wrong. You also seem to be assuming that A is symmetric matrix, but in your random test case it is not.
Following SSOR's Wikipedia entry, I replaced your P_SSOR function with
def P_SSOR(A,w):
L,D,U = splitMat(A)
P = 2/(2-w) * (1/w*D+L)*np.linalg.inv(D)*(1/w*D+L).T
return P
and your test matrix with
A = np.random.rand(100,100)
A = A + A.T
and your code works up to a 12 digit residual error.

How to solve a large probability matrix of a Markov Chain with two servers in Python?

I'm trying to make a transition matrix of a Markov Chain with two servers, however, the initialisation seems to continuously go wrong. P[i][j] gives an error with undefined [i] and undefined [j], in the log it gives: local variable 'i' referenced before assignment. Somebody got any idea how to solve this?
import numpy as np
k = 1000
N = 15000
Lambda = 3
Mu1 = 196
Mu2 = 300
c = 2
P = []
def get_transition_matrix(
c,
N,
Lambda,
Mu1,
Mu2
):
P[i][j] = np.zeros((N + 1, N + 1))
for i in range(N+1):
for j in range(N+1):
if i > 0 and 0 < j < N:
P[i][j] = 0
if j == N and i == 0:
P[i][j] = 0.5
if i == 0 and N > j > 0:
P[i][j] = ((Mu1* P[0][j-1]) + (Mu2 * P[0][j+1]))/ (Lambda + Mu2)
return P[i][j]
P[i][j] = get_transition_matrix(c, N, Lambda, Mu1, Mu2)
print(P[i][j])

Normalized correlation

I have trouble with the use of the normalized correlation. I am using python to plot the different plots, such as correlation, normalized correlation and auto-correlation.
When I use my own defined function with a sinus it works well, but when I try the Wikipedia example with a triangle and a box wave the normalized correlation does not work anymore.
This is the code I use (only the functions):
def crosscor(sig, known):
ans = np.array([])
temp = 0
for i in range(len(sig)-len(known)):
for j in range(len(known)):
temp += sig[i+j]*known[j]
ans = np.append(ans, temp)
temp = 0
return ans
def normcrosscor(sig, known):
ans = np.array([])
temp = 0
x2 = 0
y2 = 0
for i in range(len(sig)-len(known)):
for j in range(len(known)):
x2 += (sig[i+j]-np.mean(sig[i:i+len(known)]))**2
y2 += (known[j]-np.mean(known))**2
sigx = (1/len(known)*x2)**(1/2)
sigy = (1/len(known)*y2)**(1/2)
for j in range(len(known)):
if sigx != 0 and sigy != 0:
temp += (sig[i+j]-np.mean(sig[i:i+len(known)]))*(known[j]-np.mean(known))/(sigx*sigy)
else:
temp += 0
temp = 1/len(known)*temp
ans = np.append(ans, temp)
x2 = 0
y2 = 0
temp = 0
return ans
def autocor(sig):
x = sig
y = sig
ans = np.array([])
y = np.lib.pad(y, (len(sig), len(sig)), 'constant', constant_values=(0, 0))
for t in range(len(y)-len(sig)+1):
s = 0
for i in range(len(x)):
s += x[i]*y[i+t]
ans = np.append(ans, s)
return ans
When I try this with a sinus my result is as follow:
And when I use a triangle wave and a blok wave to compare the signals I get:
I expect that the normalized correlation would also give me a result that has a maximum near 100.
Can somebody help me?

Scikit-learn: How to run KMeans on a one-dimensional array?

I have an array of 13.876(13,876) values between 0 and 1. I would like to apply sklearn.cluster.KMeans to only this vector to find the different clusters in which the values are grouped. However, it seems KMeans works with a multidimensional array and not with one-dimensional ones. I guess there is a trick to make it work but I don't know how. I saw that KMeans.fit() accepts "X : array-like or sparse matrix, shape=(n_samples, n_features)", but it wants the n_samples to be bigger than one
I tried putting my array on a np.zeros() matrix and run KMeans, but then is putting all the non-null values on class 1 and the rest on class 0.
Can anyone help in running this algorithm on a one-dimensional array?
You have many samples of 1 feature, so you can reshape the array to (13,876, 1) using numpy's reshape:
from sklearn.cluster import KMeans
import numpy as np
x = np.random.random(13876)
km = KMeans()
km.fit(x.reshape(-1,1)) # -1 will be calculated to be 13876 here
Read about Jenks Natural Breaks. Function in Python found the link from the article:
def get_jenks_breaks(data_list, number_class):
data_list.sort()
mat1 = []
for i in range(len(data_list) + 1):
temp = []
for j in range(number_class + 1):
temp.append(0)
mat1.append(temp)
mat2 = []
for i in range(len(data_list) + 1):
temp = []
for j in range(number_class + 1):
temp.append(0)
mat2.append(temp)
for i in range(1, number_class + 1):
mat1[1][i] = 1
mat2[1][i] = 0
for j in range(2, len(data_list) + 1):
mat2[j][i] = float('inf')
v = 0.0
for l in range(2, len(data_list) + 1):
s1 = 0.0
s2 = 0.0
w = 0.0
for m in range(1, l + 1):
i3 = l - m + 1
val = float(data_list[i3 - 1])
s2 += val * val
s1 += val
w += 1
v = s2 - (s1 * s1) / w
i4 = i3 - 1
if i4 != 0:
for j in range(2, number_class + 1):
if mat2[l][j] >= (v + mat2[i4][j - 1]):
mat1[l][j] = i3
mat2[l][j] = v + mat2[i4][j - 1]
mat1[l][1] = 1
mat2[l][1] = v
k = len(data_list)
kclass = []
for i in range(number_class + 1):
kclass.append(min(data_list))
kclass[number_class] = float(data_list[len(data_list) - 1])
count_num = number_class
while count_num >= 2: # print "rank = " + str(mat1[k][count_num])
idx = int((mat1[k][count_num]) - 2)
# print "val = " + str(data_list[idx])
kclass[count_num - 1] = data_list[idx]
k = int((mat1[k][count_num] - 1))
count_num -= 1
return kclass
Use and visualization:
import numpy as np
import matplotlib.pyplot as plt
def get_jenks_breaks(...):...
x = np.random.random(30)
breaks = get_jenks_breaks(x, 5)
for line in breaks:
plt.plot([line for _ in range(len(x))], 'k--')
plt.plot(x)
plt.grid(True)
plt.show()
Result:

Categories