Changing line color in Line2d - Python GIF - python

I created an algorithm to solve the TSP problem. I want to present the result in the form of a GIF that shows the distance traveled. I use line2d from the Matplotlib library for this purpose. Every time the car reaches the starting point, I want to change the color of the line. I am currently using the line2d.set_color () functions for this. Unfortunately, it causes a color change of the entire road. My goal is to change the color at any given moment while keeping the previous colors. Can you help me with this problem?
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import random
from gurobipy import Model, GRB, quicksum
from matplotlib import collections as mc
rnd = np.random
rnd.seed()
n = 20 # numbre of clients
xc = rnd.rand(n + 1) * 200
yc = rnd.rand(n + 1) * 100
xc[0] = 100
yc[0] = 50
N = [i for i in range(1, n + 1)]
V = [0] + N
A = [(i, j) for i in V for j in V if i != j]
c = {(i, j): np.hypot(xc[i] - xc[j], yc[i] - yc[j]) for i, j in A}
Q = 30
# q = {i: random.choice([-5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) for i in N}
# q = {i: random.choice([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) for i in N}
q = {i: rnd.randint(1, 10) for i in N}
# a = [['x', xc], ['y', yc], ['Capacity', q]]
# for i in range(len(a)) :
# for j in range(len(a[i])):
# print(a[i][j], end=" ")
# print()
mdl = Model('CVRP')
x = mdl.addVars(A, vtype=GRB.BINARY)
u = mdl.addVars(N, vtype=GRB.CONTINUOUS)
mdl.modelSense = GRB.MINIMIZE
mdl.setObjective(quicksum(x[i, j] * c[i, j] for i, j in A))
mdl.addConstrs(quicksum(x[i, j] for j in V if j != i) == 1 for i in N)
mdl.addConstrs(quicksum(x[i, j] for i in V if i != j) == 1 for j in N)
mdl.addConstrs((x[i, j] == 1) >> (u[i] + q[j] == u[j])
for i, j in A if i != 0 and j != 0)
mdl.addConstrs(u[i] >= q[i] for i in N)
mdl.addConstrs(u[i] <= Q for i in N)
mdl.Params.MIPGap = 0.1
mdl.Params.TimeLimit = 30 # seconds
mdl.optimize()
active_arcs = [a for a in A if x[a].x > 0.99]
final_arcs = []
roads = 0
while len(active_arcs) != 0:
temp_arcs = [active_arcs[0]]
for i, j in temp_arcs:
temp_j = j
i2 = 0
while temp_j != 0:
for i, j in active_arcs:
if temp_j == i and temp_j != 0:
temp_arcs.append(active_arcs[i2])
temp_j = j
i2 += 1
i2 = 0
i = 0
i2 = 0
while i < len(temp_arcs):
while i2 < len(active_arcs):
if temp_arcs[i] == active_arcs[i2]:
active_arcs.pop(i2)
i2 += 1
i += 1
i2 = 0
final_i = 0
while final_i < len(temp_arcs):
final_arcs.append(temp_arcs[final_i])
final_i += 1
temp_arcs.clear()
roads += 1
plt.plot(xc[0], yc[0], c='r', marker='s')
for i in N:
if q[i] > 0:
plt.scatter(xc[i], yc[i], c='b')
else:
plt.scatter(xc[i], yc[i], c='y')
plt.show()
print('Liczba wykonanych tras: ', roads)
# for i, j in final_arcs:
# plt.plot([xc[i], xc[j]], [yc[i], yc[j]], color, zorder=0)
# if j == 0:
# if len(colors_base) != 0:
# c = random.randint(0, len(colors_base) - 1)
# color = colors_base[c]
# colors_base.pop(c)
#
# plt.show()
fig, ax = plt.subplots()
ax.set_xlim(0, 200)
ax.set_ylim(0, 100)
x_data, y_data = [], []
ln1, ln2 = [], []
ln, = plt.plot([], [], zorder=0)
colors_base = ['r', 'cyan', 'black', 'orange', 'm', 'darkorchid', 'dimgray', 'indigo', 'lawngreen', 'darkred']
ln.set_color('g')
plt.plot(xc[0], yc[0], 'r', marker='s')
for i in N:
if q[i] > 0:
plt.scatter(xc[i], yc[i], c='b')
else:
plt.scatter(xc[i], yc[i], c='y')
tmp = 0
for i, j in final_arcs:
x_data_tmp = [xc[i], xc[j]]
y_data_tmp = [yc[i], yc[j]]
x_data.append(x_data_tmp)
y_data.append(y_data_tmp)
def update(p):
ln1.append(x_data[p])
ln2.append(y_data[p])
ln.set_data(ln1, ln2)
for i, j in final_arcs:
if yc[i] == 50 and y_data[p] == [yc[i], yc[j]] and p != 0:
if len(colors_base) != 0:
color = colors_base[0]
ln.set_color(color)
colors_base.pop(0)
return ln,
ani = FuncAnimation(fig, update, frames=len(final_arcs), interval=1000)
ani.save('animation.gif', fps=3)
# ani.save('animation.mp4', fps=3)
plt.show()
This is how the received gif looks like:
enter image description here

One possible solution:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import random
from gurobipy import Model, GRB, quicksum
from matplotlib import collections as mc
rnd = np.random
rnd.seed()
n = 20 # numbre of clients
xc = rnd.rand(n + 1) * 200
yc = rnd.rand(n + 1) * 100
xc[0] = 100
yc[0] = 50
N = [i for i in range(1, n + 1)]
V = [0] + N
A = [(i, j) for i in V for j in V if i != j]
c = {(i, j): np.hypot(xc[i] - xc[j], yc[i] - yc[j]) for i, j in A}
Q = 30
# q = {i: random.choice([-5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) for i in N}
# q = {i: random.choice([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) for i in N}
q = {i: rnd.randint(1, 10) for i in N}
mdl = Model('CVRP')
x = mdl.addVars(A, vtype=GRB.BINARY)
u = mdl.addVars(N, vtype=GRB.CONTINUOUS)
mdl.modelSense = GRB.MINIMIZE
mdl.setObjective(quicksum(x[i, j] * c[i, j] for i, j in A))
mdl.addConstrs(quicksum(x[i, j] for j in V if j != i) == 1 for i in N)
mdl.addConstrs(quicksum(x[i, j] for i in V if i != j) == 1 for j in N)
mdl.addConstrs((x[i, j] == 1) >> (u[i] + q[j] == u[j])
for i, j in A if i != 0 and j != 0)
mdl.addConstrs(u[i] >= q[i] for i in N)
mdl.addConstrs(u[i] <= Q for i in N)
mdl.Params.MIPGap = 0.1
mdl.Params.TimeLimit = 30 # seconds
mdl.optimize()
active_arcs = [a for a in A if x[a].x > 0.99]
final_arcs = []
roads = 0
while len(active_arcs) != 0:
temp_arcs = [active_arcs[0]]
for i, j in temp_arcs:
temp_j = j
i2 = 0
while temp_j != 0:
for i, j in active_arcs:
if temp_j == i and temp_j != 0:
temp_arcs.append(active_arcs[i2])
temp_j = j
i2 += 1
i2 = 0
i = 0
i2 = 0
while i < len(temp_arcs):
while i2 < len(active_arcs):
if temp_arcs[i] == active_arcs[i2]:
active_arcs.pop(i2)
i2 += 1
i += 1
i2 = 0
final_i = 0
while final_i < len(temp_arcs):
final_arcs.append(temp_arcs[final_i])
final_i += 1
temp_arcs.clear()
roads += 1
fig, ax = plt.subplots()
ax.set_xlim(0, 200)
ax.set_ylim(0, 100)
x_data, y_data = [], []
ln1, ln2 = [], []
ln, = ax.plot([], [], zorder=0)
colors_base = ['r', 'cyan', 'black', 'orange', 'm', 'darkorchid', 'dimgray', 'indigo', 'lawngreen', 'darkred']
ln.set_color('g')
plt.plot(xc[0], yc[0], 'r', marker='s')
for i in N:
if q[i] > 0:
plt.scatter(xc[i], yc[i], c='b')
else:
plt.scatter(xc[i], yc[i], c='y')
# precompute each line coordinates
lines_data = []
xd, yd = [], []
for i, j in final_arcs:
xd.append(xc[i])
yd.append(yc[i])
if j == 0:
xd.append(xc[0])
yd.append(yc[0])
lines_data.append([xd, yd])
xd, yd = [], []
# add empty lines with the specified colors
lines = []
for i in range(len(lines_data)):
lines.append(ax.plot([], [], color=colors_base[i])[0])
def update(p):
global current_line, up_to_point
# reset after each animation cycle is complete
if current_line > len(lines_data) - 1:
current_line = 0
for l in lines:
l.set_data([], [])
up_to_point += 1
xd, yd = lines_data[current_line]
lines[current_line].set_data(xd[:up_to_point], yd[:up_to_point])
if len(xd[:up_to_point]) == len(xd):
current_line += 1
up_to_point = 1
# index of the line to animate
current_line = 0
# draw the current line up to the point of this index
up_to_point = 1
ani = FuncAnimation(fig, update, frames=len(final_arcs), interval=1000)
ani.save('animation.gif', fps=3)
# ani.save('animation.mp4', fps=3)
plt.show()

Related

converting code to be able to use Multiprocessing

I have a rather long question I hope I can get help with.
I have a code that runs a simulation by a "while true" loop and after that a "for" loop that saves data from the simulation and restart the sim after given time. This code works fine, but now Im trying to convert this into a multiprocess where I can get 4 simultaneous simulations and for loops. So I tried to put most of the code into a function and then called it but it does not seem to work. Sorry for the long code I appreciate any help!
The first working code without multiprocessing
for z in range(8):
for q in range(100):
time_re = time_re + 3000
tk.after(time_re,appender)
tk.after(time_re,restart)
ava(avaR1)
while True:
time_steps = range(0,iterations+1)
B = Beta.get()
G = Gamma.get()
D = Diff.get()
M = Mor.get()
steps_x_or_y = np.random.rand(n)
steps_x = steps_x_or_y < D/2
steps_y = (steps_x_or_y > D/2) & (steps_x_or_y < D)
nx = (x + np.sign(np.random.randn(n)) * steps_x) % l
ny = (y + np.sign(np.random.randn(n)) * steps_y) % l
for i in np.where( (S==1) & ( np.random.rand(n) < B ))[0]: # loop over infecting agents
S[(x==x[i]) & (y==y[i]) & (S==0)] = 1 # Susceptiples together with infecting agent becomes infected
S[ (S==1) & (np.random.rand(n) < G) ] = 2 # Recovery
S[ (S==1) & (np.random.rand(n) < M) ] = 3 # Death
nrInf1 = sum(S==1)
nrSus.append(sum(S==0))
nrInf.append(sum(S==1))
nrRec.append(sum(S==2))
nrRec1 = sum(S==2)
nrDea = sum(S == 3)
iterations += 1
tk.update()
tk.title('Infected:' + str(np.sum(S==1)))
x = nx # Update x
y = ny # Update y
The second code with me trying to change it to multiprocessing
def main1(i):
# Physical parameters of the system
x = np.floor(np.random.rand(n)*l) # x coordinates
y = np.floor(np.random.rand(n)*l) # y coordinates
S = np.zeros(n) # status array, 0: Susceptiple, 1: Infected, 2: recovered
I = np.argsort((x-l/2)**2 + (y-l/2)**2)
S[I[1:initial_infected]] = 1 # Infect agents that are close to center
nrRec1 = 0
nrDea = []
time_re = 0
particles = []
R = .5 # agent plot radius
nx = x # udpated x
ny = y # updated y
def restart():
global S
I = np.argsort((x-l/2)**2 + (y-l/2)**2)
S = np.zeros(n)
S[I[1:initial_infected]] = 1
rest = Button(tk, text='Restart',command= restart)
rest.place(relx=0.05, rely=.85, relheight= 0.12, relwidth= 0.15 )
def ava(k,o):
global b
k.append(sum(o)/3)
Beta.set(b) # Parameter slider for mortality rate
b += 0.03125
#bSaver.append(b)
def appender(o):
nrDea1.append(nrDea)
o.append(nrRec1)
for j in range(n): # Generate animated particles in Canvas
particles.append( canvas.create_oval( (x[j] )*res/l,
(y[j] )*res/l,
(x[j]+2*R )*res/l,
(y[j]+2*R )*res/l,
outline=ccolor[0], fill=ccolor[0]) )
if i == 1:
b=0
for z in range(3):
for q in range(3):
time_re = time_re + 1000
tk.after(time_re,appender(nrSRec1))
tk.after(time_re,restart)
tk.after(9000,ava(avaR1,nrSRec1))
elif i == 2:
b=0.25
for z in range(3):
for q in range(3):
time_re = time_re + 1000
tk.after(time_re,appender(nrSRec2))
tk.after(time_re,restart)
tk.after(9000,ava(avaR2,nrSRec2))
elif i == 3:
b=.50
for z in range(3):
for q in range(3):
time_re = time_re + 1000
tk.after(time_re,appender(nrSRec3))
tk.after(time_re,restart)
tk.after(9000,ava(avaR3,nrSRec3))
else:
b=.75
for z in range(3):
for q in range(3):
time_re = time_re + 1000
tk.after(time_re,appender(nrSRec4))
tk.after(time_re,restart)
tk.after(9000,ava(avaR4,nrSRec4))
while True:
B = Beta.get()
G = Gamma.get()
D = Diff.get()
steps_x_or_y = np.random.rand(n)
steps_x = steps_x_or_y < D/2
steps_y = (steps_x_or_y > D/2) & (steps_x_or_y < D)
nx = (x + np.sign(np.random.randn(n)) * steps_x) % l
ny = (y + np.sign(np.random.randn(n)) * steps_y) % l
for i in np.where( (S==1) & ( np.random.rand(n) < B ))[0]: # loop over infecting agents
S[(x==x[i]) & (y==y[i]) & (S==0)] = 1 # Susceptiples together with infecting agent becomes infected
S[ (S==1) & (np.random.rand(n) < G) ] = 2 # Recovery
nrDea= sum(S == 3)
nrRec1 = sum(S==2)
tk.update()
tk.title('Infected:' + str(np.sum(S==1)))
x = nx # Update x
y = ny # Update y
if __name__ == '__main__':
p1=mp.Process(target=main1, args=(1,))
p1.start()
p2=mp.Process(target=main1, args=(2,))
p2.start()
p3=mp.Process(target=main1, args=(3,))
p3.start()
p4=mp.Process(target=main1, args=(4,))
p4.start()
joinedList = avaR1+avaR2+avaR3+avaR4
print(joinedList)
Tk.mainloop(canvas)

def __rmul__ -> TypeError: can't multiply sequence by non-int of type 'float'

Hi guys I'm new to python and I have an assignment based on Classes and I am getting an error with my code while I try to def__rmul__ . TypeError: can't multiply sequence by non-int of type 'float'. I would appreciate if someone can explain the error to this code. Thanks a lot ! I also cant upload the entire code for some reason it says : I need to write more ...
def cg(A, b, epsilon=1e-4):
# k = 0, kk = k + 1
xk = Vector([0.] * b.rows)
rk = b - A * xk
pk = 1. * rk
for k in range(b.rows):
alpha = (rk * rk) / (pk * (A * pk))
xkk = xk + alpha * pk
rkk = rk - alpha * (A * pk)
if rkk.norm() < epsilon:
break
beta = (rkk * rkk) / (rk * rk)
pkk = rkk + beta * pk
rk = rkk
pk = pkk
xk = xkk
return xkk
A = np.array([
[2., 3.],
[4., 5.],
])
b = np.array([1., 2.])
x = np.zeros(2)
for i in range(2):
for j in range(2):
x[i] += A[i][j] * b[j]
print(x)
x = np.dot(A, b)
print(x)
A = np.array([2., 3., 4., 5.])
b = np.array([1., 2.])
x = np.zeros(2)
for i in range(2):
for j in range(2):
x[i] += A[i * 2 + j] * b[j]
print(x)
A = np.array([2., 4., 3., 5.])
b = np.array([1., 2.])
x = np.zeros(2)
for i in range(2):
for j in range(2):
x[i] += A[j * 2 + i] * b[j]
print(x)
A = [
(0, 0, 2.),
(0, 1, 3.),
(1, 0, 4.),
(1, 1, 5.),
]
b = np.array([1., 2.])
x = np.zeros(2)
for i, j, aij in A:
x[i] += aij * b[j]
print(x)
class Vector(object):
def __init__(self, data):
self.data = data
self.rows = len(data)
def __mul__(self, other):
assert self.rows == other.rows
return sum([vi * vj for vi, vj in zip(self.data, other.data)])
def __rmul__(self, a):
data = [a * d for d in self.data]
return Vector(data)
def __add__(self, other):
assert self.rows == other.rows
return Vector([i + j for (i, j) in zip(self.data, other.data)])
def __sub__(self, other):
assert self.rows == other.rows
return Vector([i - j for (i, j) in zip(self.data, other.data)])
def norm(self):
return math.sqrt(self * self)
def __str__(self):
return '{0}'.format(self.data)
class Matrix(object):
def __init__(self, rows, cols):
self.rows = rows
self.cols = cols
def cg(self, b, epsilon=1e-4):
... # [1]
self.data = data
xk = Vector([0.] * b.rows)
rk = b - A * xk
pk = 1. * rk
for k in range(b.rows):
alpha = (rk * rk) / (pk * (A * pk))
xkk = xk + alpha * pk
rkk = rk - alpha * (A * pk)
if rkk.norm() < epsilon:
break
beta = (rkk * rkk) / (rk * rk)
pkk = rkk + beta * pk
rk = rkk
pk = pkk
xk = xkk
return xkk
#exit()
class FullMatrix(Matrix):
def __init__(self, rows, cols, data):
super().__init__(rows, cols)
self.data = data
def __mul__(self, v):
assert self.cols == v.rows
data = [0.] * self.rows
... # [2]
for i in range(self.rows):
for j in range(self.cols):
data[i] += self.data[i+j*self.rows]*v.data[j]
return Vector(data)
class SparseMatrix(Matrix):
def __init__(self, rows, cols, triplets):
super().__init__(rows, cols)
self.triplets = triplets
def __mul__(self, v):
assert self.cols == v.rows
data = [0.] * self.rows
... # [3]
for (i,j,d) in self.triplets:
data[i] += d*v.data[j]
return Vector(data)
if __name__ == "__main__":
sizes = [2 ** i for i in (2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)]
t_full = []
t_sparse = []
for N in sizes:
print('_' * 80)
print("size : {0}".format(N))
# b - vector
data = [0. for i in range(N)]
data[-1] = 10
b = Vector(data)
# Af - full matrix
data = [0.] * (N * N)
for i in range(N - 1):
data[i + N * i ] = 10.
data[i + 1 + N * i ] = -0.1
data[i + N * (i + 1)] = -0.1
data[N - 1 + N * (N - 1)] = 10.
Af = FullMatrix(N, N, data)
# solve
t0 = time.time()
#~ xf = cg(Af, b)
xf = Af.cg(b)
tf = time.time() - t0
t_full.append(tf)
print("full : time: {0:6.2f}s (x[-1] = {1:12.10g})".format(tf, xf.data[-1]))
# As - sparse
triplets = []
for i in range(N - 1):
triplets.append((i, i, 10.))
triplets.append((i + 1, i, -0.1))
triplets.append((i, i + 1, -0.1))
triplets.append((N - 1, N - 1, 10.))
As = SparseMatrix(N, N, triplets)
# solve
t0 = time.time()
#~ xs = cg(As, b)
xs = As.cg(b)
ts = time.time() - t0
t_sparse.append(ts)
print("sparse : time: {0:6.2f}s (x[-1] = {1:12.10g})".format(ts, xs.data[-1]))
# An - numpy
An = np.zeros((N, N))
for i in range(N - 1):
An[i, i] = 10
An[i + 1, i] = -0.1
An[i, i + 1] = -0.1
# solve
An[N - 1, N - 1] = 10.
t0 = time.time()
xn = np.linalg.solve(An, b.data)
tn = time.time() - t0
print("numpy : time: {0:6.2f}s (x[-1] = {1:12.10g})".format(tn, xn[-1]))
print()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(sizes, t_full, 'b-o', label='full')
ax.plot(sizes, t_sparse, 'r-o', label='sparse')
ax.set_xlabel('size')
ax.set_ylabel('times [s]')
ax.grid()
ax.legend()
plt.show()

Recursive function that remembers its path in global list python

I have problem with function:
tested_zeros = [(-1, -1)]
def reveal_zeros(x, y):
board_visible[y*row+x] = board[y*row+x]
for p in range(x - 1, x + 2):
for o in range(y - 1, y + 2):
if o >= 0 and p >= 0 and o <= row and p <= col:
for zero in tested_zeros:
if zero != (p, o):
tested_zeros.append((p, o)) <--broke part in my 'super' idea xD
if board[o*row+p] == " ":
return reveal_zeros(p, o)
so what is doing is checking if in array 'board[(x, y)]' is zero and its neighbors, when it is, its copying it to 'board_visible', the problem is that it bugs in (0, 0),[and calling it endlessly] so my idea was adding list tested_zeros so he remembers which points it tested but recursive function does not works that way :), and i know i can check last by(x, y) but it will loop somewhere else.
My question is how to handle this?
Here is my whole code:
import random
import numpy as np
row = 10
col = row
mine_list = list()
board = list()
board_visible = list()
num = 0
is_over = False
def get_num_of_mines():
global num
while True:
print("Podaj liczbe min: \n(z zakresu od 1 do ", (row * col) - 1, ")")
num = int(input())
if 1 <= num <= (row * col) - 1:
return num
else:
print("Błędna liczba. Podaj poprawną z zakresu")
def deploy_mines():
global mine_list
mine_x = random.randint(0, row - 1)
mine_y = random.randint(0, col - 1)
par = mine_x, mine_y
for l in mine_list:
if par == l:
return deploy_mines()
return mine_x, mine_y
def number_of_neighboring_mines(x, y):
global mine_list
num_of_neighbors = 0
for p in range(x - 1, x + 2):
for o in range(y - 1, y + 2):
if o >= 0 and p >= 0 and o <= row and p <= col:
par = p, o
for l in mine_list:
if par == l:
num_of_neighbors += 1
if num_of_neighbors == 0:
return " "
else:
return num_of_neighbors
def add_bomb(x, y):
for l in mine_list:
if (x, y) == l:
board.append("*")
return False
return True
def create_board():
global mine_list, num, board_visible
for k in range(0, num):
mine_list.append(deploy_mines())
for i in range(0, col):
for j in range(0, row):
if add_bomb(i, j):
board.append(number_of_neighboring_mines(i, j))
for i in range(0, col):
for j in range(0, row):
board_visible.append(chr(9552))
def show_board():
for l in range(0, col+1):
print('{0:2d}'.format(l), end="\t")
print()
for l in range(0, col):
print('{0:2d}'.format(l+1), end=" ")
print(np.split(np.asarray(board), row)[l])
def print_board():
for l in range(0, col+1):
print('{0:2d}'.format(l), end="\t")
print()
for l in range(0, col):
print('{0:2d}'.format(l+1), end=" ")
print(np.split(np.asarray(board_visible), row)[l])
tested_zeros = [(-1, -1)]
def reveal_zeros(x, y):
board_visible[y*row+x] = board[y*row+x]
for p in range(x - 1, x + 2):
for o in range(y - 1, y + 2):
if o >= 0 and p >= 0 and o <= row and p <= col:
for zero in tested_zeros:
if zero != (p, o) or zero is None:
print(p, o)
tested_zeros.append((p, o))
if board[o*row+p] == " ":
return reveal_zeros(p, o)
def reveal_squares(x, y):
global is_over
if board[y*row+x] == "*":
show_board()
print("Koniec gry!")
is_over = True
elif board[y*row+x] == " ":
reveal_zeros(x, y)
else:
board_visible[y*row+x] = board[y*row+x]
def sapper():
get_num_of_mines()
create_board()
while not is_over:
print_board()
reveal_squares(int(input("Podaj współrzędną x: "))-1, int(input("Podaj
współrzędną y: "))-1)
sapper()
I came up with a working function:
def reveal_zeros(x, y, steps):
board_visible[y*row+x] = board[y*row+x]
can_return = True
for p in range(x - 1, x + 2):
for o in range(y - 1, y + 2):
if o >= 0 and p >= 0 and o < row and p < col:
for i in steps:
if (p, o) == i:
can_return = False
if board[o*row+p] == " " and can_return:
return reveal_zeros(p, o, steps + [(p, o)])
if p == x or o == y or o < 0 or p < 0 or not can_return:
can_return = True
continue
return
Here is a sapper simulation with no winning.

How do I get my data in my heatmap?

I've programmed Conways Game of Life in Python and now I'm trying to display the simple data that it gives me as an output in a heat map.
This is my current code:
from Tkinter import *
import matplotlib.pyplot as plt
import time
import numpy as np
import random
size_x = 100
size_y = 10
# create the matrices
cell = [[0 for row in range(0, size_y)] for col in range(0, size_x)]
live = [[0 for row in range(0, size_y)] for col in range(0, size_x)]
temp = [[0 for row in range(0, size_y)] for col in range(0, size_x)]
# process and draw the next frame
def frame():
process()
draw()
root.after(100, frame)
# load the initial data
def load(initial=0.5):
for y in range(0, size_y):
for x in range(0, size_x):
if random.random()<initial: live[x][y] = 1
temp[x][y] = 0
# Applying rules
def process():
for y in range(0, size_y):
for x in range(0, size_x):
lives = live_neighbors(x,y)
if live[x][y] == 1:
if lives < 2 or lives > 3:
temp[x][y] = 0
else:
temp[x][y] = 1
if live[x][y] == 0:
if lives == 3:
temp[x][y] = 1
else:
temp[x][y] = 0
for y in range(0, size_y):
for x in range(0, size_x):
live[x][y] = temp[x][y]
# live = temp
# Count live neighbors
def live_neighbors(a,b):
lives = 0
if live[a][(b+1)%size_y] == 1: lives += 1
if live[a][(b-1)%size_y] == 1: lives += 1
if live[(a+1)%size_x][b] == 1: lives += 1
if live[(a+1)%size_x][(b+1)%size_y] == 1: lives += 1
if live[(a+1)%size_x][(b-1)%size_y] == 1: lives += 1
if live[(a-1)%size_x][b] == 1: lives += 1
if live[(a-1)%size_x][(b+1)%size_y] == 1: lives += 1
if live[(a-1)%size_x][(b-1)%size_y] == 1: lives += 1
return lives
# Draw all cells
def draw():
nLiving = 0
nDead = 0
for y in range(size_y):
for x in range(size_x):
if live[x][y]==0:
canvas.itemconfig(cell[x][y], fill="black")
nDead+=1
if live[x][y]==1:
canvas.itemconfig(cell[x][y], fill="white")
nLiving+=1
print nLiving,nDead
# count cells
def count():
nLiving = 0
nDead = 0
for y in range(size_y):
for x in range(size_x):
if live[x][y]==0:
nDead+=1
if live[x][y]==1:
nLiving+=1
z = nLiving / 10.0
print z,
print "%"
def one_game(initial):
load(initial)
for gen in range(1, 101):
print str(gen) + ":",
count()
process()
def many_games():
numbers = range(1,51)
for initial in numbers:
print initial/100.0
one_game(initial/100.0)
many_games()
#one_game(0.5)
The code for making a normal heat map with given input would be:
fig, ax = plt.subplots(1)
x = np.array( [[11,12,13], [21,22,23], [31,32,33]] )
p = ax.pcolormesh(x)
fig.colorbar(p)
plt.show()
How do I get my data (which in this case would be, the generations, the value which initializes the one_game() function, and nLiving) into an array?
I'm not 100% sure this is what you're intending, but it produced a pretty output heat map :)
def count():
nLiving = 0
nDead = 0
for y in range(size_y):
for x in range(size_x):
if live[x][y]==0:
nDead+=1
if live[x][y]==1:
nLiving+=1
z = nLiving / 10.0
print("nLiving over ten is: ", z,)
print("%")
return nLiving
def one_game(initial):
load(initial)
gen_array = []
for gen in range(1, 101):
print("Gen: ", str(gen) + ":",)
nLiving = count()
process()
gen_array.append(nLiving)
return gen_array
def many_games():
gen_output = []
numbers = range(1,51)
for initial in numbers:
print(initial/100.0)
gen_array = one_game(initial/100.0)
gen_output.append(gen_array)
return gen_output
gen_output = many_games()
#one_game(0.5)
fig, ax = plt.subplots(1)
x = np.array( gen_output )
p = ax.pcolormesh(x)
fig.colorbar(p)
plt.show()
That is just code modified from your count function to the end of the file. Basically you just need to return the output from the functions that you're calling into the right kind of data structures, I think...

SVM: problems with SMO algorithm

I'm currently trying to code a non linear SVM for handwritten digits recognition using the MNIST data base.
I chose to use the SMO algorithm (based on Platt's paper and other books), but I have some trouble implementing it.
When I run the code over the training set, the bias goes higher and higher, sometimes until "Inf" value, leading the SVM to "classify" every example in the same class.
Here is my code:
import numpy
import gzip
import struct
import matplotlib
from sklearn import datasets
from copy import copy
class SVM:
def __init__(self, constant, data_set, label_set):
self._N = len(data_set)
if self._N != len(label_set):
raise Exception("Data size and label size don't match.")
self._C = constant
self._epsilon = 0.001
self._tol = 0.001
self._data = [numpy.ndarray.flatten((1/255)*elt) for elt in data_set]
self._dimension = len(self._data[0])
self._label = label_set
self._alphas = numpy.zeros((1, self._N))
self._b = 0
self._errors = numpy.ndarray((2, 0))
def kernel(self, x1, x2):
x1 = x1.reshape(1,self._dimension)
result = numpy.power(numpy.dot(x1, x2), 3)
return result
def evaluate(self, x):
result = 0
i = 0
while i < self._N:
result += self._alphas[0, i]*self._label[i]*self.kernel(x, self._data[i])
i += 1
result += self._b
return result
def update(self, i1, i2, E2):
i1 = int(i1)
i2 = int(i2)
if i1 == i2:
return 0
y1 = self._label[i1]
y2 = self._label[i2]
alpha1 = self._alphas[0, i1]
alpha2 = self._alphas[0, i2]
#If alpha1 is non-bound, its error is in the cache.
#So we check its position to extract its error.
#Else, we compute it.
if alpha1 > 0 and alpha1 < self._C :
position = 0
for i, elt in enumerate(self._errors[0, :]):
if elt == i1:
position = i
E1 = self._errors[1, position]
else:
E1 = self.evaluate(self._data[i1]) - y1
s = y1*y2
H = L = 0
if y1 != y2:
L = max(0, alpha2 - alpha1)
H = min(self._C, self._C + alpha2 - alpha1)
else:
L = max(0, alpha2 + alpha1 - self._C)
H = min(self._C, alpha2 + alpha1)
if H == L:
return 0
K11 = self.kernel(self._data[i1], self._data[i1])
K12 = self.kernel(self._data[i1], self._data[i2])
K22 = self.kernel(self._data[i2], self._data[i2])
eta = K11 + K22 - 2*K12
if eta > 0:
alpha2_new = alpha2 + (y2*(E1 - E2)/eta)
if alpha2_new < L:
alpha2_new = L
elif alpha2_new > H:
alpha2_new = H
else:
f1 = y1*(E1 + self._b) - alpha1*K11 - s*alpha2*K12
f2 = y2*(E2 + self._b) - alpha2*K22 - s*alpha1*K12
L1 = alpha1 + s*(alpha2 - L)
H1 = alpha1 + s*(alpha2 - H)
FuncL = L1*f1 + L*f2 + (1/2)*numpy.square(L1)*K11 + (1/2)*numpy.square(L)*K22 + s*L1*L*K12
FuncH = H1*f1 + H*f2 + (1/2)*numpy.square(H1)*K11 + (1/2)*numpy.square(H)*K22 + s*H1*H*K12
if FuncL < FuncH - self._epsilon:
alpha2_new = L
elif FuncL > FuncH + self._epsilon:
alpha2_new = H
else:
alpha2_new = alpha2
if numpy.abs(alpha2_new - alpha2) < self._epsilon*(alpha2_new+alpha2+ self._epsilon):
return 0
alpha1_new = alpha1 + s*(alpha2 - alpha2_new)
#Update of the threshold.
b1 = E1 + y1*(alpha1_new - alpha1)*K11 + y2*(alpha2_new - alpha2)*K12 + self._b
b2 = E2 + y1*(alpha1_new - alpha1)*K12 + y2*(alpha2_new - alpha2)*K22 + self._b
if L < alpha1_new < H:
b_new = b1
elif L < alpha2_new < H:
b_new = b2
else:
b_new = (b1+b2)/2
#Update the cache error
#If alpha2 was bound and its new value is non-bound, we add its index and its error to the cache.
#If alpha2 was unbound and its new value is bound, we delete it from the cache.
if (alpha2 == 0 or alpha2 == self._C) and (alpha2_new > 0 and alpha2_new < self._C):
vector_alpha2_new = numpy.array([i2, E2])
vector_alpha2_new = vector_alpha2_new.reshape((2, 1))
self._errors = numpy.concatenate((self._errors, vector_alpha2_new), 1)
if (alpha2 > 0 and alpha2 < self._C) and (alpha2_new == 0 or alpha2_new == self._C):
l = 0
position = 0
while l < len(self._errors[0, :]):
if self._errors[0, l] == i2:
position = l
l += 1
self._errors = numpy.delete(self._errors, position, 1)
#We do the exact same thing with alpha1.
if (alpha1 == 0 or alpha1 == self._C) and (alpha1_new > 0 and alpha1_new < self._C):
vector_alpha1_new = numpy.array([i1, E1])
vector_alpha1_new = vector_alpha1_new.reshape((2, 1))
self._errors = numpy.concatenate((self._errors, vector_alpha1_new), 1)
if (alpha1 > 0 and alpha1 < self._C) and (alpha1_new == 0 or alpha1_new == self._C):
l = 0
position = 0
while l < len(self._errors[0, :]):
if self._errors[0, l] == i1:
position = l
l += 1
self._errors = numpy.delete(self._errors, position, 1)
#Then we update the error for each non bound point using the new values for alpha1 and alpha2.
for i,error in enumerate(self._errors[1, :]):
self._errors[1, i] = error + (alpha2_new - alpha2)*y2*self.kernel(self._data[i2], self._data[int(self._errors[0, i])]) + (alpha1_new - alpha1)*y1*self.kernel(self._data[i1], self._data[int(self._errors[0, i])]) - self._b + b_new
#Storing the new values of alpha1 and alpha2:
self._alphas[0, i1] = alpha1_new
self._alphas[0, i2] = alpha2_new
self._b = b_new
print(self._errors)
return 1
def examineExample(self, i2):
i2 = int(i2)
y2 = self._label[i2]
alpha2 = self._alphas[0, i2]
if alpha2 > 0 and alpha2 < self._C:
position = 0
for i, elt in enumerate(self._errors[0, :]):
if elt == i2:
position = i
E2 = self._errors[1, position]
else:
E2 = self.evaluate(self._data[i2]) - y2
r2 = E2*y2
if (r2< -self._tol and alpha2 < self._C) or (r2 > self._tol and alpha2 > 0):
n = numpy.shape(self._errors)[1]
if n > 1:
i1 = 0
if E2 > 0:
min = self._errors[1, 0]
position = 0
for l, elt in enumerate(self._errors[1, :]):
if elt < min:
min = elt
position = l
i1 = self._errors[0, position]
else:
max = self._errors[1, 0]
position = 0
for l, elt in enumerate(self._errors[1, :]):
if elt > max:
max = elt
position = l
i1 = self._errors[0, position]
if self.update(i1, i2, E2):
return 1
#loop over all non bound examples starting at a random point.
list_index = [i for i in range(n)]
numpy.random.shuffle(list_index)
for i in list_index:
i1 = self._errors[0, i]
if self.update(i1, i2, E2):
return 1
#Loop over all the training examples, starting at a random point.
list_bound = [i for i in range(self._N) if not numpy.any(self._errors[0, :] == i)]
numpy.random.shuffle(list_bound)
for i in list_bound:
i1 = i
if self.update(i1, i2, E2):
return 1
return 0
def SMO(self):
numChanged = 0
examineAll = 1
cpt = 1
while(numChanged > 0 or examineAll):
numChanged = 0
if examineAll == 1:
for i in range(self._N):
numChanged += self.examineExample(i)
else:
for i in self._errors[0, :]:
numChanged += self.examineExample(i)
if examineAll == 1:
examineAll = 0
elif numChanged == 0:
examineAll = 1
cpt += 1
def load_training_data(a, b):
train = gzip.open("train-images-idx3-ubyte.gz", "rb")
labels = gzip.open("train-labels-idx1-ubyte.gz", "rb")
train.read(4)
labels.read(4)
number_images = train.read(4)
number_images = struct.unpack(">I", number_images)[0]
rows = train.read(4)
rows = struct.unpack(">I", rows)[0]
cols = train.read(4)
cols = struct.unpack(">I", cols)[0]
number_labels = labels.read(4)
number_labels = struct.unpack(">I", number_labels)[0]
image_list = []
label_list = []
if number_images != number_labels:
raise Exception("The number of labels doesn't match with the number of images")
else:
for l in range(number_labels):
if l % 1000 == 0:
print("l:{}".format(l))
mat = numpy.zeros((rows, cols), dtype = numpy.uint8)
for i in range(rows):
for j in range(cols):
pixel = train.read(1)
pixel = struct.unpack(">B", pixel)[0]
mat[i][j] = pixel
image_list += [mat]
lab = labels.read(1)
lab = struct.unpack(">B", lab)[0]
label_list += [lab]
train.close()
labels.close()
i = 0
index_a = []
index_b = []
while i < number_labels:
if label_list[i] == a:
index_a += [i]
elif label_list[i] == b:
index_b += [i]
i += 1
image_list = [m for i,m in enumerate(image_list) if (i in index_a) | (i in index_b)]
mean = (a+b)/2
label_list = [ numpy.sign(m - mean) for l,m in enumerate(label_list) if l in index_a+index_b]
return ([image_list, label_list])
def load_test_data():
test = gzip.open("t10k-images-idx3-ubyte.gz", "rb")
labels = gzip.open("t10k-labels-idx1-ubyte.gz", "rb")
test.read(4)
labels.read(4)
number_images = test.read(4)
number_images = struct.unpack(">I", number_images)[0]
rows = test.read(4)
rows = struct.unpack(">I", rows)[0]
cols = test.read(4)
cols = struct.unpack(">I", cols)[0]
number_labels = labels.read(4)
number_labels = struct.unpack(">I", number_labels)[0]
image_list = []
label_list = []
if number_images != number_labels:
raise Exception("The number of labels doesn't match with the number of images")
else:
for l in range(number_labels):
if l % 1000 == 0:
print("l:{}".format(l))
mat = numpy.zeros((rows, cols), dtype = numpy.uint8)
for i in range(rows):
for j in range(cols):
pixel = test.read(1)
pixel = struct.unpack(">B", pixel)[0]
mat[i][j] = pixel
image_list += [mat]
lab = labels.read(1)
lab = struct.unpack(">B", lab)[0]
label_list += [lab]
test.close()
labels.close()
return ([image_list, label_list])
data = load_training_data(0, 7)
images_training = data[0]
labels_training = data[1]
svm = SVM(0.1, images_training[0:200], labels_training[0:200])
svm.SMO()
def view(image, label=""):
print("Number : {}".format(label))
pylab.imshow(image, cmap = pylab.cm.gray)
pylab.show()
First, SMO is a fairly complicated algorithm - it is not one easy to debug in this kind of format.
Second, you are starting too high up in your testing. Some advice to help you debug your problems.
1) First, switch to using the linear kernel. Its much easier for you to compute the exact linear solution with another algorithm and compare what you are getting with the exact solution. This way its only the weight vectors and bias term. If you stay in the dual space, you'll have to compare all the coefficients and make sure things stay in the same order.
2) Start with a much simpler 2D problem where you know what the general solution should look like. You can then visualize the solution, and watch as it changes at each step - this can be a visual tool to help you find where something goes wrong.
One important thing is you said this:
b1 = E1 + y1*(alpha1_new - alpha1)*K11 + y2*(alpha2_new - alpha2)*K12 + self._b
b2 = E2 + y1*(alpha1_new - alpha1)*K12 + y2*(alpha2_new - alpha2)*K22 + self._b
Basically you're just adding to b every time with this code. Your b's should look more like this:
b1 = smo.b - E1 - y1 * (a1 - alpha1) * smo.K[i1, i1] - y2 * (a2 - alpha2) * smo.K[i1, i2]
b2 = smo.b - E2 - y1 * (a1 - alpha1) * smo.K[i1, i2] - y2 * (a2 - alpha2) * smo.K[i2, i2]
This version is not perfect, but I recommend checking apex51's version on Github for pointers:
SVM-and-sequential-minimal-optimization
The mathematical basis in the notes are very strong (despite some minor discrepancies with Platt's paper) and the code is not perfect, but a good direction for you. I would also suggest looking at other, completed SMOs and trying to tweak that code to math your needs instead of writing from scratch.

Categories