Tkinter Canvas.itemconfigure not used correctly? - python

I am currently trying to make a game of life using tkinter.
One issue though: the rectangles I create won't respond to the itemconfigure method called to change their fill color. Once the tk window opened, there seems to be no way to change their color... Here is the code used: (variable names are in french, my apologies)
from tkinter import *
from numpy import *
Res = (1000, 1000)
dim = (50, 50)
BordABord = False
F = Tk()
C = Canvas(F, height = Res[1], width = Res[0])
L = ndarray(dim, dtype = bool)
Grille = ndarray(dim)
lar = []
for i in range(2):
lar.append(Res[i] // dim[i])
for i in range(dim[0]):
x = i * lar[0]
for j in range(dim[1]):
y = j * lar[1]
Grille[i, j] = C.create_rectangle(x, y, x + lar[0], y + lar[1], fill = 'white')
L[i, j] = False
def rgbTraducteur(rgb):
return "#%02x%02x%02x" % rgb
def process():
global L
global Grille
global dim
global C
for i in range(dim[0]):
for j in range(dim[1]):
if L[i, j]:
print('processssss')
C.itemconfigure(Grille[i, j], fill = 'black')
def clic(event):
print('clic')
global L
global Res
global dim
x = int(dim[0] * event.x / Res[0])
y = int(dim[1] * event.y / Res[1])
print(x, y)
L[x, y] = not(L[x, y])
process()
def pas(event = 0):
global L
global BordABord
global dim
N = L
for i in range(dim[0]):
for j in range(dim[1]):
compte = 0
for k in range(-1, 2):
x = i + k
if BordABord or x // dim[0] == 0:
x %= dim[0]
for l in range(-1, 2):
if l != 0 and k != 0:
y = j + l
if BordABord or y // dim[1] == 0:
y %= dim[1]
compte += L[x, y]
if L[i, j]:
N[i, j] = (compte - 2) // 2 == 0
else:
N[i, j] = compte == 3
L = N
process()
F.bind('<Button-1>', clic)
F.bind('<Return>', pas)
C.pack()
F.mainloop()
it is, of course, not optimised at all, and all rectangles have been set to turn black whenever process() is called as a test.

Canvas items are given an integer identifier. You must use the integer to refer to the item. A floating point number such as 1.0 does not refer to the item with an integer identifier of 1.
The problem in your code is that Grille is an array of floating point numbers. When you do Grille[i, j] = C.create_rectangle(...), create_rectangle will return an integer but it gets stored as floating point. Thus, your call to itemconfigure tries to change something with the floating point number 1.0 rather than the integer id of 1. If you pass something that is not an integer to itemconfigure the canvas assumes it is a tag. Since no elements have the tag 1.0, no elements are configured.
If you change the array to hold integers so that the numbers aren't converted, itemconfigure will work fine.
Grille = ndarray(dim, dtype=int)

Related

binom.pmf only returning zero

code:
def expected_profit(n):
total = 0
X = np.arange(0,n+1)
p = np.arange(0,n+1)
profit = np.arange(0,n+1)
for i in list(range(1,n+1)):
print("X_i:", X[i])
p[i] = binom.pmf(X[i],n,19/20)
print(p[i])
if X[i] > 100:
profit[i] = 50*n-60*(X[i]-100)
else:
profit[i] = 50*n
total += profit[i]*p[i]
return total
expected_profit(10)
>>>0
For some reason, after each iteration, p[i] is equal to zero. Yet when I manually type out (for example) binom.pmf(10,10,19/20) I get a non zero answer. What is the problem here?
This seems to happen with any call to binom.pmf within the function call.
With p = np.arange(0,n+1) you initialize p with an integer array 0,...,n. That makes that binom.pmf(...) is converted to an integer when assigned to p[i]. The solution is to make p an array of floats. np.zeros() by default creates an array of floats. The same problem holds for profit.
Fitting this into the code would look like:
from scipy.stats import binom
import numpy as np
def expected_profit(n):
n = 10
total = 0
X = np.arange(0, n + 1)
p = np.zeros(n + 1, dtype=float)
profit = np.zeros(n + 1, dtype=float)
for i in range(1, n + 1):
p[i] = binom.pmf(X[i], n, 19/20)
if X[i] > 100:
profit[i] = 50 * n - 60 * (X[i] - 100)
else:
profit[i] = 50 * n
total += profit[i] * p[i]
expected_profit(10)

box stacking algorithm , each box used once

Given a group of boxes. I want arrange the boxes on top of each other to reach the maximum height. box cannot be placed on top of another box unless the area of 2D base is <= the 2D base of the lower box. allowed to rotated any box to use any two sides as its base.
For example, consider below 4 boxes where each box has the following dimensions
Input: Box 1: (4,5,2), Box 2:(3,1,6), Box 3:(3,2,1), Box 4:(6,8,3)
Output: From bottom to top as follows:
Box 4 on the base (6,3) and height 8,
then Box 1 on the base (4,2) and height 5,
then Box 2 on the base (1,3) and height 6,
finally, on top Box 3 on the base (2,1) and height 3.
The total height is 22
this solution is work but use all instances of all boxes but i need use only one instance for each box.
this code get the same height but use the box 2 twice and ignore another box
the problem is in if statement in this 2 for loop
> for i in range(1, n):
for j in range(0, i):
if (rot[i].w <= rot[j].w and rot[i].l <= rot[j].l) and rot[i].boxNo != rot[j].boxNo:
if msh[i] < msh[j] + rot[i].h:
msh[i] = msh[j] + rot[i].h
how to prevent using the same box twice?
class Box:
def __init__(self,l, w, h):
self.h = h
self.w = w
self.l = l
self.boxNo = 0
def __lt__(self,other):
return self.l * self.w < other.l * other.w
def maxStackHeight(arr, n):
# Create an array of all rotations of given boxes.
rot = [Box(0, 0, 0) for _ in range(3 * n)]
index = 0
no=1
for i in range(n):
# original box
rot[index].h = arr[i].h
rot[index].l = max(arr[i].l, arr[i].w)
rot[index].w = min(arr[i].l, arr[i].w)
rot[index].boxNo=no
index = index+ 1
# First rotation
rot[index].h = arr[i].w
rot[index].l = max(arr[i].h, arr[i].l)
rot[index].w = min(arr[i].h, arr[i].l)
rot[index].boxNo = no
index = index + 1
# Second rotation
rot[index].h = arr[i].l
rot[index].l = max(arr[i].h, arr[i].w)
rot[index].w = min(arr[i].h, arr[i].w)
rot[index].boxNo = no
index = index + 1
no=no+1
n=n*3 # new number of boxes
rot.sort(reverse=True) #Sort array in descending order of base area
msh = [0] * n
for i in range(n):
msh[i] = rot[i].h
# Compute optimized msh values in bottom up manner
for i in range(1, n):
for j in range(0, i):
if (rot[i].w <= rot[j].w and rot[i].l <= rot[j].l) and rot[i].boxNo != rot[j].boxNo:
if msh[i] < msh[j] + rot[i].h:
msh[i] = msh[j] + rot[i].h
maxm = -1
for i in range(n):
maxm = max(maxm, msh[i])
return maxm
arr = [Box(4,5,2),Box(3,1,6),Box(3,2,1),Box(6,8,3)]
n = len(arr)
print("The maximum possible height of stack is",maxStackHeight(arr, n))
This ought to do the trick, it uses itertools module to create every possible combination of the boxes using cartesian product, and only checks ones that meet the criteria for your problem.
from itertools import product
class Box:
def __init__(self,l, w, h):
self.h = h
self.w = w
self.l = l
self.boxNo = 0
def __lt__(self,other):
return self.l * self.w < other.l * other.w
def maxStackHeight(arr, n):
# Create an array of all rotations of given boxes.
rot = [Box(0, 0, 0) for _ in range(3 * n)]
numBoxes = n
index = 0
no=1
for i in range(n):
# original box
rot[index].h = arr[i].h
rot[index].l = max(arr[i].l, arr[i].w)
rot[index].w = min(arr[i].l, arr[i].w)
rot[index].boxNo=no
index = index+ 1
# First rotation
rot[index].h = arr[i].w
rot[index].l = max(arr[i].h, arr[i].l)
rot[index].w = min(arr[i].h, arr[i].l)
rot[index].boxNo = no
index = index + 1
# Second rotation
rot[index].h = arr[i].l
rot[index].l = max(arr[i].h, arr[i].w)
rot[index].w = min(arr[i].h, arr[i].w)
rot[index].boxNo = no
index = index + 1
no=no+1
rot.sort(reverse=True) #Sort array in descending order of base area
# Compute optimized msh values in bottom up manner
workable = []
for combo in product(rot, repeat = numBoxes):
if len(set(b.boxNo for b in combo)) != numBoxes:
continue
canwork = True
for a, b in zip(combo[:-1], combo[1:]):
if a < b :
canwork = False
if canwork:
workable.append(combo)
return max(sum(box.h for box in combo) for combo in workable)
arr = [Box(4,5,2),Box(3,1,6),Box(3,2,1),Box(6,8,3)]
n = len(arr)
print("The maximum possible height of stack is",maxStackHeight(arr, n))

how to append local variable from function to array/list in python?

How to append local variable from inside function to array/list in python?
below is my code.
I want to append corr variable to an empty array.
suppose T=[] .
its not appending and going in infinite loop.
how can I do this?
# Python Program to find correlation coefficient.
import math
# function that returns correlation coefficient.
def correlationCoefficient(X, Y, n) :
sum_X = 0
sum_Y = 0
sum_XY = 0
squareSum_X = 0
squareSum_Y = 0
i = 0
while i < n :
# sum of elements of array X.
sum_X = sum_X + X[i]
# sum of elements of array Y.
sum_Y = sum_Y + Y[i]
# sum of X[i] * Y[i].
sum_XY = sum_XY + X[i] * Y[i]
# sum of square of array elements.
squareSum_X = squareSum_X + X[i] * X[i]
squareSum_Y = squareSum_Y + Y[i] * Y[i]
z = ((float)(math.sqrt((n * squareSum_X -sum_X * sum_X)* (n * squareSum_Y -sum_Y * sum_Y))))
y = ((float)(n * sum_XY - sum_X * sum_Y))
i = i + 1
if z == 0:
corr = 0
else:
# use formula for calculating correlation coefficient.
corr=abs(y/z)
while corr<1:
T=[]
T.append(corr)
print("T",T)
return corr
# Driver function
A = [0,7.6,7.7,6.4,6.25,6.4,6.4,5.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.3,6.4,3.2,3.2,3.25,3.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5.35,5,4.85,5.65,5.4,5.35,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
B = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86]
X = [0]*5
Y = [0]*5
# the size of array.
n=5
# Function call to correlationCoefficient.
k=0
while k <= len(A):
i = k
m = 0
while i <= k+4:
X[m] = A[i]
#print("A[i]",A[i])
Y[m] = B[i]
#print("B[i]",B[i])
i = i + 1
m = m + 1
#correlationCoefficient(X, Y, 5)
print ((correlationCoefficient(X, Y, 5)))
k = k + 1
The relevant bit seems to be here:
corr=abs(y/z)
while corr<1:
T=[]
T.append(corr)
print("T",T)
return corr
You're blanking out the T array each time that while loop runs, and it will run forever if corr<1, since you never change the value of corr.
Move T=[] outside of the while i<n loop if you'd like it to stick around, and modify corr (or use an if instead) to avoid the infinite loop.

Python 3.4.3 Diamond-Square Algorithm is producing odd results

I am currently stumped by an artefact in my code. It appears to produce very sharp points in a grid pattern that have a noticeable difference in value to their neighbours.
I am following the blog post at http://www.bluh.org/code-the-diamond-square-algorithm/ and converting from whichever language they are using (assuming either C# or Java), and have double-checked that what I am doing should match.
Is there any chance that someone could have a browse over this, and see what I'm doing wrong? I've stepped through it at smaller levels, and stopped it on specific iterations of the algorithm (by unrolling the top loop, and explicitly calling the algorithm a set number of times) and everything seems to work until we get to the very last set of points/pixels.
I use a class (called Matrix) to access the list, and wrap any out of bounds values.
The code for the algorithm is as follows:
class World :
def genWorld (self, numcells, cellsize, seed):
random.seed(seed)
self.dims = numcells*cellsize
self.seed = seed
self.cells = Matrix(self.dims, self.dims)
# set the cells at cellsize intervals
half = cellsize/2
for y in range(0, self.dims, cellsize):
for x in range(0, self.dims, cellsize):
self.cells[x,y] = random.random()
scale = 1.0
samplesize = cellsize
while samplesize > 1:
self._diamondSquare(samplesize, scale)
scale *= 0.8
samplesize = int(samplesize/2)
# I need to sort out the problem with the diamond-square algo that causes it to make the weird gridding pattern
def _sampleSquare(self, x, y, size, value):
half = size/2
a = self.cells[x-half, y-half]
b = self.cells[x+half, y-half]
c = self.cells[x-half, y+half]
d = self.cells[x+half, y+half]
res = min(((a+b+c+d+value)/5.0), 1.0)
self.cells[x, y] = res
def _sampleDiamond(self, x, y, size, value):
half = size/2
a = self.cells[x+half, y]
b = self.cells[x-half, y]
c = self.cells[x, y+half]
d = self.cells[x, y-half]
res = min(((a+b+c+d+value)/5.0), 1.0)
self.cells[x, y] = res
def _diamondSquare(self, stepsize, scale):
half = int(stepsize/2)
for y in range(half, self.dims+half, stepsize):
for x in range(half, self.dims+half, stepsize):
self._sampleSquare(x, y, stepsize, random.random()*scale)
for y in range(0, self.dims, stepsize):
for x in range(0, self.dims, stepsize):
self._sampleDiamond(x+half, y, stepsize, random.random()*scale)
self._sampleDiamond(x, y+half, stepsize, random.random()*scale)
and is called with:
w = World()
w.genWorld(16, 16, 1) # a 256x256 square world, since the numcells is multiplied by the cellsize to give us the length of ONE side of the resulting grid
then I save to file to check the result:
file = io.open("sample.raw",'wb')
arr = [int(i * 255) for i in w.cells.cells] # w.cells.cells should not have a value >= 1.0, so what's going on?
ind = 0
for a in arr:
if a > 255:
print ("arr["+str(ind)+"] ::= "+str(a))
ind += 1
file.write(bytearray(arr))
file.close()
which gives the result:
EDIT: Okay, so it appears that I managed to get it working. I swapped from using functions for working out the diamond and square steps to doing it all in the _diamondSquare() function, but this wasn't the only thing. I also found out that random.random() provides values in the range [0.0 ->1.0), when I was expecting values in the range [-1.0 -> 1.0). After I corrected this, everything started working properly, which was a relief.
Thanks for the advice everyone, here's the working code in case anyone else is struggling with something similar:
Random Function
# since random.random() gives a value in the range [0.0 -> 1.0), I need to change it to [-1.0 -> 1.0)
def rand():
mag = random.random()
sign = random.random()
if sign >=0.5:
return mag
return mag * -1.0
Matrix class
class Matrix:
def __init__(self, width, height):
self.cells = [0 for i in range(width*height)]
self.width = width
self.height = height
self.max_elems = width*height
def _getsingleindex(self, ind):
if ind < 0:
ind *= -1
while ind >= self.max_elems:
ind -= self.max_elems
return ind
def _getmultiindex(self, xind, yind):
if xind < 0:
xind *= -1
if yind < 0:
yind *= -1
while xind >= self.width:
xind -= self.width
while yind >= self.height:
yind -= self.height
return xind + (yind*self.height)
def __getitem__(self, inds):
# test that index is an integer, or two integers, and throw an indexException if not
if hasattr(inds, "__len__"):
if len(inds) > 1:
return self.cells[self._getmultiindex(int(inds[0]), int(inds[1]))]
return self.cells[self._getsingleindex(int(inds))]
def __setitem__(self, inds, object):
# test that index is an integer, or two integers, and throw an indexException if not
if hasattr(inds, "__len__"):
if len(inds) > 1:
self.cells[self._getmultiindex(int(inds[0]),int(inds[1]))] = object
return self.cells[self._getmultiindex(int(inds[0]),int(inds[1]))]
self.cells[self._getsingleindex(int(inds))] = object
return self.cells[self._getsingleindex(int(inds))]
def __len__(self):
return len(self.cells)
The Actual Diamond-Square Generation
# performs the actual 2D generation
class World:
def genWorld (self, numcells, cellsize, seed, scale = 1.0):
random.seed(seed)
self.dims = numcells*cellsize
self.seed = seed
self.cells = Matrix(self.dims, self.dims)
mountains = Matrix(self.dims, self.dims)
# set the cells at cellsize intervals
for y in range(0, self.dims, cellsize):
for x in range(0, self.dims, cellsize):
# this is the default, sets the heights randomly
self.cells[x,y] = random.random()
while cellsize > 1:
self._diamondSquare(cellsize, scale)
scale *= 0.5
cellsize = int(cellsize/2)
for i in range(len(mountains)):
self.cells[i] = self.cells[i]*0.4 + (mountains[i]*mountains[i])*0.6
def _diamondSquare(self, stepsize, scale):
half = int(stepsize/2)
# diamond part
for y in range(half, self.dims+half, stepsize):
for x in range(half, self.dims+half, stepsize):
self.cells[x, y] = ((self.cells[x-half, y-half] + self.cells[x+half, y-half] + self.cells[x-half, y+half] + self.cells[x+half, y+half])/4.0) + (rand()*scale)
# square part
for y in range(0, self.dims, stepsize):
for x in range(0, self.dims, stepsize):
self.cells[x+half,y] = ((self.cells[x+half+half, y] + self.cells[x+half-half, y] + self.cells[x+half, y+half] + self.cells[x+half, y-half])/4.0)+(rand()*scale)
self.cells[x,y+half] = ((self.cells[x+half, y+half] + self.cells[x-half, y+half] + self.cells[x, y+half+half] + self.cells[x, y+half-half])/4.0)+(rand()*scale)
Main Function (added for completeness)
# a simple main function that uses World to create a 2D array of diamond-square values, then writes it to a file
def main():
w = World()
w.genWorld(20, 16, 1)
mi = min(w.cells.cells)
ma = max(w.cells.cells) - mi
# save the resulting matrix to an image file
file = io.open("sample.raw",'wb')
maxed = [(i-mi)/ma for i in w.cells.cells]
arr = [int(i * 255) for i in maxed]
file.write(bytearray(arr))
file.close()

Python implementation of gradient descent (Machine Learning)

I have tried to implement gradient descent here in python but the cost J just seems to be increasing irrespective of lambda ans alpha value, i am unable to figure out what the issue over here is. It'll be great if someone can help me out with this. The input is a matrix Y and R with same dimensions. Y is a matrix of movies x users and R is just to say if a user has rated a movie.
#Recommender system ML
import numpy
import scipy.io
def gradientDescent(y,r):
(nm,nu) = numpy.shape(y)
x = numpy.mat(numpy.random.randn(nm,10))
theta = numpy.mat(numpy.random.randn(nu,10))
for i in range(1,10):
(x,theta) = costFunc(x,theta,y,r)
def costFunc(x,theta,y,r):
X_tmp = numpy.power(x , 2)
Theta_tmp = numpy.power(theta , 2)
lmbda = 0.1
reg = ((lmbda/2) * numpy.sum(Theta_tmp))+ ((lmbda/2)*numpy.sum(X_tmp))
ans = numpy.multiply(numpy.power(((theta * x.T).T - y),2) , r)
res = (0.5 * numpy.sum(ans))+reg
print "J:",res
print "reg:",reg
(nm,nu) = numpy.shape(y)
X_grad = numpy.mat(numpy.zeros((nm,10)));
Theta_grad = numpy.mat(numpy.zeros((nu,10)));
alpha = 0.1
# [m f] = size(X);
(m,f) = numpy.shape(x);
for i in range(0,m):
for k in range(0,f):
tmp = 0
# X_grad(i,k) += (((theta * x'(:,i)) - y(i,:)').*r(i,:)')' * theta(:,k);
tmp += ((numpy.multiply(((theta * x.T[:,i]) - y[i,:].T),r[i,:].T)).T) * theta[:,k];
tmp += (lmbda*x[i,k]);
X_grad[i,k] -= (alpha*tmp)
# X_grad(i,k) += (lambda*X(i,k));
# [m f] = size(Theta);
(m,f) = numpy.shape(theta);
for i in range(0,m):
for k in range(0,f):
tmp = 0
# Theta_grad(i,k) += (((theta(i,:) * x') - y(:,i)').*r(:,i)') * x(:,k);
tmp += (numpy.multiply(((theta[i,:] * x.T) - y[:,i].T),r[:,i].T)) * x[:,k];
tmp += (lmbda*theta[i,k]);
Theta_grad[i,k] -= (alpha*tmp)
# Theta_grad(i,k) += (lambda*Theta(i,k));
return(X_grad,Theta_grad)
def main():
mat1 = scipy.io.loadmat("C:\Users\ROHIT\Machine Learning\Coursera\mlclass-ex8\ex8_movies.mat")
Y = mat1['Y']
R = mat1['R']
r = numpy.mat(R)
y = numpy.mat(Y)
gradientDescent(y,r)
#if __init__ == '__main__':
main()
I did not check the whole code logic, but assuming it is correct, your costfunc is supposed to return gradient of the cost function, and in these lines:
for i in range(1,10):
(x,theta) = costFunc(x,theta,y,r)
you are overwriting the last values of x and theta with its gradient, while gradient is the measure of change, so you should move in the opposite direction (substract the gradient instead of overwriting the values):
for i in range(1,10):
(x,theta) -= costFunc(x,theta,y,r)
But it seems that you already assign the minus sign to the gradient in your costfunc so you should add this value instead
for i in range(1,10):
(x,theta) += costFunc(x,theta,y,r)

Categories

Resources