I can't figure out why my code isn't working, very frustrating. I constantly get the error: int object has no attribute to append (for average.append(i, average//250)). But I can't figure out what exactly is wrong here. Is it not possible to import other definition in append functions?
I hope somebody can help me out!
Any help with my code in general is appreciated :)
def main():
average = []
y_values = []
for x in range(0, 2501, 500):
for i in range(250):
average.append(calculate(x))
average = sum(average)
print("{} euro, {} worpen".format(i, average//250))
y_values.append(average//250)
x_values = [0, 500, 1000, 1500, 2000, 2500]
y_values = []
plt.plot(x_values, y_values)
plt.xlabel("Startgeld")
plt.ylabel("Aantal worpen")
plt.title("Monopoly")
plt.show()
def calculate(game_money):
piece = monopoly.Piece()
board = monopoly.Board()
owns = possession(board)
dice = throw()
throw_count = 0
number = 0
total_throw = 0
while not all(owns.values()):
number == throw()
piece.move(number)
total_throw = total_throw + number
throw_count += 1
if total_throw > 40:
game_money += 200
elif board.values[piece.location] > 0:
if game_money > board.values[piece.location]:
if owns[board.names[piece.location]] == False:
owns[board.names[piece.location]] = True
game_money = game_money - board.values[piece.location]
return total_throw
def throw():
dice = randint(1,6) + randint(1,6)
return dice
def possession(board):
owns = {}
for i in range(40):
if board.values[i] > 0:
owns[board.names[i]] = False
return owns
if __name__ == "__main__":
main()
You done a small mistake in your code. See my comment below and correct your code accordingly. Good Luck :-)
y_values = []
average = []
for x in range(0, 2501, 500):
for i in range(250):
average.append(calculate(x))
#average = sum(average) #This is your mistake. Now onward average will be considered as int object make it like below
average1 = sum(average)
print("{} euro, {} worpen".format(i, average1//250))
y_values.append(average1//250)
Related
I am trying to understand how to implement a genetic algorithm and wrote a simple string guess. I am having trouble understanding why this solution is not working.
I believe that my problem is in my populating my new generations? The newest generations do not seem to have improved fitness values. I am also not sure if I am doing the crossover and mutation rates correctly. Any help would be really appreciated!
POP_SIZE = 300;
CROSSOVER_RATE = 0.7;
MUTATION_RATE = 0.01
GENESET = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"
target = "Hello World"
RAND_NUM = random.random()
def generateBasePopulation(population_size):
population = dict()
for _ in range(POP_SIZE):
gene = generateParent(len(target))
population[gene] = 0
return population
def generateNewPopulation(population, population_size):
newPopulation = dict()
while(len(newPopulation) <= POP_SIZE):
child_one, child_two = crossover(child_one, child_two)
child_one = mutate(child_one)
child_two = mutate(child_two)
newPopulation[child] = 0
newPopulation[child_two] = 0
return newPopulation
def assignFitness(population):
for x in population:
population[x] = getFitness(x)
def generateParent(length):
genes = list("")
for i in range(0,length):
random_gene = random.choice(GENESET)
genes.append(random_gene)
return(''.join(genes))
def getFitness(candidate):
fitness = 0
for i in range(0, len(candidate) - 1):
if target[i] == candidate[i]:
fitness += 1
return(fitness)
def mutate(parent):
gene_index_to_mutate = random.randint(0, len(parent) - 1)
mutation_value = random.choice(GENESET)
genes = list(parent)
genes[gene_index_to_mutate] = mutation_value
return(''.join(genes))
def crossover(parentA, parentB):
if(RAND_NUM < CROSSOVER_RATE):
random_index = random.randint(0, len(target))
parentASlice = parentA[:random_index]
parentBSlice = parentB[random_index:]
return (parentASlice + parentBSlice), (parentBSlice + parentASlice)
return parentA, parentB
def chooseChild(population):
fitnessSum = sum(population.values())
pick = random.uniform(0, fitnessSum)
current = 0
for pop in population:
current += population[pop]
if current >= pick:
return pop
def main():
population = generateBasePopulation(POP_SIZE)
targetNotFound = True
while(targetNotFound):
assignFitness(population)
if target in population:
print("target found!")
targetNotFound = False
if(targetNotFound):
tempPopulation = generateNewPopulation(population, POP_SIZE)
population.clear()
population = tempPopulation
There are some issues with the generateNewPopulation function.
child_one and child_two are referenced before assignment
You need two individuals from the population to perform the crossover. There are several selection algorithms, but just to give an idea you could start with a form of tournament selection:
def extractFromPopulation(population):
best = random.choice(list(population.keys()))
for _ in range(4):
gene = random.choice(list(population.keys()))
if population[gene] > population[best]:
best = gene
return best
Here the selection pressure (range(4)) is fixed. It's one of the parameters you've to tune in a real case.
Now we have:
def generateNewPopulation(population, population_size):
newPopulation = dict()
while len(newPopulation) <= POP_SIZE:
child_one = extractFromPopulation(population)
child_two = extractFromPopulation(population)
# ...
The code still doesn't work because
new individuals aren't inserted in newPopulation
Just indent the two lines:
newPopulation[child] = 0
newPopulation[child_two] = 0
(they must be part of the while loop)
The revised generateNewPopulation function follows:
def generateNewPopulation(population, population_size):
newPopulation = dict()
while len(newPopulation) <= POP_SIZE:
child_one = extractFromPopulation(population)
child_two = extractFromPopulation(population)
child_one, child_two = crossover(child_one, child_two)
child_one = mutate(child_one)
child_two = mutate(child_two)
newPopulation[child_one] = 0
newPopulation[child_two] = 0
return newPopulation
The crossover function cannot be based on a fixed RAND_NUM value
Delete the RAND_NUM = random.random() assignment and change the crossover function to use a new random value at each call:
def crossover(parentA, parentB):
if random.random() < CROSSOVER_RATE:
random_index = random.randint(0, len(target))
parentASlice = parentA[:random_index]
parentBSlice = parentB[random_index:]
return (parentASlice + parentBSlice), (parentBSlice + parentASlice)
return parentA, parentB
Also the code doesn't correctly perform single point crossover since schemata of the second parent aren't preserved.
You could change many details to improve performance but, as a starting example, it's probably enough as it is (...it works).
Average number of generations to find a solution is about 158 (average on 200 runs).
EDIT (thanks to alexis for the comment)
MUTATION_RATE is unused and a mutation always happens. The mutate function should be something like:
def mutate(parent):
if random.random() < MUTATION_RATE:
gene_index_to_mutate = random.randint(0, len(parent) - 1)
mutation_value = random.choice(GENESET)
genes = list(parent)
genes[gene_index_to_mutate] = mutation_value
return ''.join(genes)
return parent
This fix is particularly important if you keep the roulette wheel selection algorithm (chooseChild often doesn't converge without the fix).
I've been trying to code game of life by my own as I want to learn python and I thought that could be a good practice and I have just finish except I need to pass a variable to another method but I really dont know how I know it could seem dumb
but wait a bit and see the code is not that easy as it sound unless for me
import random,time
f=3
c=3
contador = 0
tablero = []
tablero_dibujado = []
class juego(object):
def tablero(self): #Create the Board
for i in range(f):
tablero.append([0]*c)
tablero_dibujado.append([0]*c)
def rellenar_tablero_random(self): #Fill the board with random 0 and 1
for i in range(f):
for j in range(c):
tablero[i][j] = random.randint(0,1)
print(tablero)
def rellenar_tablero_manual(self): #Just to fill the board manually if I want for some reason
tablero[0][1] = 1
for i in range(2):
tablero[1][i] = 1
print(tablero)
def distancia_vecino(self,cell_f,cell_c): #Measure Distance for possible neighbours
distancia_vecino = [(-1,-1),(-1,0),(-1,1),(0,1),(1,1),(1,0),(1,-1),(0,-1)]
for i in range(8):
string = distancia_vecino[i]
comparar_string = str(string)
x,y = comparar_string.split(",")
x = str(x).replace(",","")
y = str(y).replace(",","")
x = x.replace("(","")
y = y.replace(")","")
y = y.replace(" ","")
x = int(x) + cell_f
y = int(y) + cell_c
if x>=f or x<0:
continue
else:
if y>=c or y<0:
continue
else:
game.detectar_vecino(cell_f,cell_c,x,y)
game.vida(cell_f,cell_c)
def detectar_vecino(self, cell_f, cell_c, x, y): #Check how many neighboards do I have
vecinos = 0
if tablero[cell_f][cell_c] == 1:
if tablero[cell_f][cell_c] == tablero[x][y]:
vecinos+=1
else:
if tablero[cell_f][cell_c] != tablero[x][y]:
vecinos+=1
contador = contador + vecinos
def iterar_tablero(self): #Just to iterate all the board to check the values
for i in range(f):
for j in range(c):
game.distancia_vecino(i,j)
a = input() #In order to the screen dont close after executing it
def vida(self, cell_f, cell_c): #Check if they are alive and if they should be alive or dead
print(contador)
if tablero[cell_f][cell_c] == 1:
if contador > 3 or contador < 2:
tablero[cell_f][cell_c] = 0
else:
if contador == 3:
tablero[cell_f][cell_c] = 1
game.dibujar_tablero()
def dibujar_tablero(self): #Draw the board in a more clearly way
contador1 = 0
for i in range(f):
for j in range(c):
if tablero[i][j] == 1:
tablero_dibujado[i][j] = "§"
else:
tablero_dibujado[i][j] = "■"
for i in tablero_dibujado:
print(" ")
for j in i:
print(j, end=" ")
print("")
time.sleep(2)
game = juego()
game.tablero()
game.rellenar_tablero_manual()
game.iterar_tablero()
What I need is that in detectar_vecino have to get all the neighbour of a cell in the board and the problem is that doing it I got : local variable 'contador' referenced before assignment. And I know why it happen.However I couldnt find any alternative way of doing it so please if anyone know how can I solve it.
I just want to clarify that this isnt any work from anywhere,Im doing it just by my own as a hobby and with this I just want to finish with thank you for your time I appreciate it
Add this line global contador like below
def detectar_vecino(self, cell_f, cell_c, x, y):
global contador # Add this line.
vecinos = 0
if tablero[cell_f][cell_c] == 1:
if tablero[cell_f][cell_c] == tablero[x][y]:
vecinos+=1
else:
if tablero[cell_f][cell_c] != tablero[x][y]:
vecinos+=1
contador = contador + vecinos
I've been playing around with sympy and decided to make an arbitrary equations solver since my finance class was getting a little dreary. I wrote a basic framework and started playing with some examples, but some work and some don't for some reason.
from sympy import *
import sympy.mpmath as const
OUT_OF_BOUNDS = "Integer out of bounds."
INVALID_INTEGER = "Invalid Integer."
INVALID_FLOAT = "Invalid Float."
CANT_SOLVE_VARIABLES = "Unable to Solve for More than One Variable."
CANT_SOLVE_DONE = "Already Solved. Nothing to do."
# time value of money equation: FV = PV(1 + i)**n
# FV = future value
# PV = present value
# i = growth rate per perioid
# n = number of periods
FV, PV, i, n = symbols('FV PV i n')
time_value_money_discrete = Eq(FV, PV*(1+i)**n)
time_value_money_continuous = Eq(FV, PV*const.e**(i*n))
def get_sym_num(prompt, fail_prompt):
while(True):
try:
s = input(prompt)
if s == "":
return None
f = sympify(s)
return f
except:
print(fail_prompt)
continue
equations_supported = [['Time Value of Money (discrete)', [FV, PV, i, n], time_value_money_discrete],
['Time Value of Money (continuous)',[FV, PV, i, n], time_value_money_continuous]]
EQUATION_NAME = 0
EQUATION_PARAMS = 1
EQUATION_EXPR = 2
if __name__ == "__main__":
while(True):
print()
for i, v in enumerate(equations_supported):
print("{}: {}".format(i, v[EQUATION_NAME]))
try:
process = input("What equation do you want to solve? ")
if process == "" or process == "exit":
break
process = int(process)
except:
print(INVALID_INTEGER)
continue
if process < 0 or process >= len(equations_supported):
print(OUT_OF_BOUNDS)
continue
params = [None]*len(equations_supported[process][EQUATION_PARAMS])
for i, p in enumerate(equations_supported[process][EQUATION_PARAMS]):
params[i] = get_sym_num("What is {}? ".format(p), INVALID_FLOAT)
if params.count(None) > 1:
print(CANT_SOLVE_VARIABLES)
continue
if params.count(None) == 0:
print(CANT_SOLVE_DONE)
continue
curr_expr = equations_supported[process][EQUATION_EXPR]
for i, p in enumerate(params):
if p != None:
curr_expr = curr_expr.subs(equations_supported[process][EQUATION_PARAMS][i], params[i])
print(solve(curr_expr, equations_supported[process][EQUATION_PARAMS][params.index(None)]))
This is the code I have so far. I guess I can strip it down to a basic example if need be, but I was also wondering if there was a better way to implement this sort of system. After I have this down, I want to be able to add arbitrary equations and solve them after inputting all but one parameter.
For example, if I put in (for equation 0), FV = 1000, PV = 500, i = .02, n is empty I get 35.0027887811465 which is the correct answer. If I redo it and change FV to 4000, it returns an empty list as the answer.
Another example, when I input an FV, PV, and an n, the program seems to hang. When I input small numbers, I got RootOf() answers instead of a simple decimal.
Can anyone help me?
Side note: I'm using SymPy 0.7.6 and Python 3.5.1 which I'm pretty sure are the latest
This is a floating point accuracy issue. solve by default plugs solutions into the original equation and evaluates them (using floating point arithmetic) in order to sort out false solutions. You can disable this by setting check=False. For example, for Hugh Bothwell's code
for fv in range(1870, 1875, 1):
sols = sp.solve(eq.subs({FV:fv}), check=False)
print("{}: {}".format(fv, sols))
which gives
1870: [66.6116466112007]
1871: [66.6386438584579]
1872: [66.6656266802551]
1873: [66.6925950919998]
1874: [66.7195491090752]
I don't have an answer, but I do have a much simpler demonstration case ;-)
import sympy as sp
FV, n = sp.symbols("FV n")
eq = sp.Eq(FV, sp.S("500 * 1.02 ** n"))
# see where it breaks
for fv in range(1870, 1875, 1):
sols = sp.solve(eq.subs({FV:fv}))
print("{}: {}".format(fv, sols))
which produces
1870: [66.6116466112007]
1871: [66.6386438584579]
1872: []
1873: []
1874: []
At a guess this is where the accuracy breaks down enough that it can't find a verifiable solution for n?
Also, while poking at this I did a fairly extensive rewrite which you may find useful. It does pretty much the same as your code but in a much more loosely-coupled fashion.
import sympy as sp
class Equation:
def __init__(self, label, equality_str, eq="=="):
self.label = label
# parse the equality
lhs, rhs = equality_str.split(eq)
self.equality = sp.Eq(sp.sympify(lhs), sp.sympify(rhs))
# index free variables by name
self.vars = {var.name: var for var in self.equality.free_symbols}
def prompt_for_values(self):
# show variables to be entered
var_names = sorted(self.vars, key=str.lower)
print("\nFree variables are: " + ", ".join(var_names))
print("Enter a value for all but one (press Enter to skip):")
# prompt for values by name
var_values = {}
for name in var_names:
value = input("Value of {}: ".format(name)).strip()
if value:
var_values[name] = sp.sympify(value)
# convert names to Sympy variable references
return {self.vars[name]:value for name,value in var_values.items()}
def solve(self):
values = self.prompt_for_values()
solutions = sp.solve(self.equality.subs(values))
# remove complex answers
solutions = [sol.evalf() for sol in solutions if sol.is_real]
return solutions
def __str__(self):
return str(self.equality)
# Define some equations!
equations = [
Equation("Time value of money (discrete)", "FV == PV * (1 + i) ** n"),
Equation("Time value of money (continuous)", "FV == PV * exp(i * n)" )
]
# Create menu
menu_lo = 1
menu_hi = len(equations) + 1
menu_prompt = "\n".join(
[""]
+ ["{}: {}".format(i, eq.label) for i, eq in enumerate(equations, 1)]
+ ["{}: Exit".format(menu_hi)]
+ ["? "]
)
def get_int(prompt, lo=None, hi=None):
while True:
try:
value = int(input(prompt))
if (lo is None or lo <= value) and (hi is None or value <= hi):
return value
except ValueError:
pass
def main():
while True:
choice = get_int(menu_prompt, menu_lo, menu_hi)
if choice == menu_hi:
print("Goodbye!")
break
else:
solutions = equations[choice - 1].solve()
num = len(solutions)
if num == 0:
print("No solutions found")
elif num == 1:
print("1 solution found: " + str(solutions[0]))
else:
print("{} solutions found:".format(num))
for sol in solutions:
print(sol)
if __name__ == "__main__":
main()
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...
import numpy as np
import matplotlib.pyplot as plt
class Prisoners_Dilemma:
def __init__(self,n,p):
self.n = n
self.p = p
def decision_array(self):
self.dict_dict = {}
for i in range(1,self.n + 1):
self.dict_dict[i] = []
list_list = []
for j in range(1,self.n):
#np.random.seed(j)
self.r = np.random.uniform(0,1)
if self.r > self.p:
q = 0
else:
q = 1
list_list.append(q)
self.dict_dict[i] = list_list
return self.dict_dict
def payoff(self):
self.dict_dict_2 = {}
for i in range(1,self.n + 1):
self.dict_dict_2[i] = []
list_list_2 = []
list_list_3=[]
for j in range(1, i):
list_list_2.append(self.dict_dict[j][i-2])
for j in range(i + 1, self.n + 1):
list_list_2.append(self.dict_dict[j][i-1])
list_list_2_np = np.array(list_list_2)
against_i = np.sum(list_list_2_np)
for_i = np.sum(self.dict_dict[i])
if against_i == 0 and for_i == 0:
payoff_i = 2
elif against_i == 0 and for_i != 0:
payoff_i = 5
elif against_i != 0 and for_i == 0:
payoff_i = -5
else:
payoff_i = -2
list_list_3.append(payoff_i)
self.dict_dict_2[i]=list_list_3
return self.dict_dict_2
def gameplay(self, N, initial_count):
self.counter = initial_count
for i in range(N):
for j in range(1, self.n + 1):
z = self.dict_dict_2[j]
x = np.array(z)
self.counter += np.sum(z)
return self.counter
y = Prisoners_Dilemma(15,0.015)
print (y.gameplay(20,100))
In the above code, the compiler gives the error that instance has no attribute as dict_dict_2 even though its prefixed with self. Moreover, it is perfectly fine with dict_dict. For the sake of completeness I have included the whole code but the problem lies only in payoff and gameplay methods?
dict_dict_2 is only created in payoff(), therefore you must call it before attempting to call gameplay().
The issue is that you are only creating self.dict_dict_2 variable in the payoff function, but in your logic where you are calling gameplay() function , you are not calling the payoff() function before accessing dict_dict_2 , from the looks of it you are not calling that function anywhere at all.
Not sure what dict_dict_2 holds, but the above is the reason why you are getting the issue, maybe you can move the initialization part of dict_dict_2 to __init__() function , though that would not fix the complete issue, since you would still be trying to access dict_dict_1[j] which can error out if j is not a key in dict_dict_2 .