K
I've been looking at the above questions and based on this I leave you an approximation using POO. This way the code is reduced and scaled easily as it allows to use an undetermined number of signals, players and rounds. Some clarifications:I have removed the variable round Since, I think, you only use the list to number the round you're in, that is, it's always the way:round= [0,1,2,3,...,n]
If it is not this way it can be easily modified so that the builder accepts the list as variable.The operation of the method generar_senales() is:In round 1 the signals of each participant are determined by the order of the player and senal parameters that we pass to the builder. For example:jugadores = [1,2,3,4]
senales = ['a', 'b', 'r', 'n']
In the first round the player 1 shows the 'a' signal, the 2 'b' signal, the 3 'r' signal and the 4 'n' signal.In the second round and later use the signals of the first round to generate each signal randomly and according to the odds for each player and signal (using the functions with_b and choise).The method generar_senales() is a generator (yield) and returns a dictionary with the random signal of each player, as follows:{1: 'S8', 2: 'S6', 3: 'S5', 4: 'S1', 5: 'S3', 6: 'S7'}
This same dictionary is the one used to create the corresponding row csvThe varials s1, s2, s3, s4 I pass them into a list called s, this way we can define any number of players and signals.The way to pass the pairings I have also modified, now each round is a list that contains the pairings inside. This way it's more intuitive. However, you could still use your form with some modifications.The csv has as header (first row) the names of the players. The remaining rows are the rounds (signature shown by each player).As shown in the following execution we simulate a 4 round game with 6 players:from random import random, sample
from bisect import bisect
import csv
class Partida():
def init(self, jugadores, emparejamientos, senales, s, b, x, m):
self.emparejamientos = emparejamientos
self.senales = senales
self.s = s
self.b = b
self.x = x
self.m = m
self.jugadores = {nombre: Partida.Jugador(senales)
for pareja in emparejamientos[0]
for nombre in pareja}
self.memoria = list()
def generar_senales(self):
def with_b(muestra, observa, s, r):
if not (muestra == observa == 0):
result = ((0.98) * (1.0 - self.b) * (1.0 - self.x) * muestra/r) + ((0.98) * (1.0 - self.b) * (self.x) * observa/r) + ((0.98) * self.b * s) + ((self.m / 8))
else:
result = ((0.98) * (1.0 - 0) * (1.0 - self.x) * muestra/r) + ((0.98) * (1.0 - 0) * (self.x) * observa/r) + ((0.98) * 0 * s) + ((self.m / 8))
return result
def choice(opciones, probs):
probAcumuladas = list()
aux = 0
for p in probs:
aux += p
probAcumuladas.append(aux)
r = random() * probAcumuladas[-1]
op = bisect(probAcumuladas, r)
return opciones[op]
yield dict(zip(self.jugadores.keys(), self.senales))
r = 1
while True:
eleccs = dict.fromkeys(self.jugadores.keys())
for nombre, inst in self.jugadores.items():
probs = [with_b(inst.mem_mostradas[op], inst.men_observadas[op], self.s[indx], r)
for indx, op in enumerate(self.senales)]
eleccs[nombre] = choice(self.senales, probs)
r += 1
yield eleccs
def jugar(self):
gen_sens = self.generar_senales()
for n, ronda in enumerate(self.emparejamientos):
senales = next(gen_sens)
self.memoria.append(senales)
for jugador1, jugador2 in ronda:
self.jugadores[jugador1].men_observadas[senales[jugador2]] += 1
self.jugadores[jugador2].men_observadas[senales[jugador1]] += 1
self.jugadores[jugador1].mem_mostradas[senales[jugador1]] += 1
self.jugadores[jugador2].mem_mostradas[senales[jugador2]] += 1
class Jugador():
def __init__(self, senales):
self.mem_mostradas = {senal: 0 for senal in senales}
self.men_observadas = {senal: 0 for senal in senales}
def main():
jugadores = [1, 2, 3, 4, 5, 6]
senales = ['S1', 'S2', 'S3', 'S4', 'S5', 'S6']
emparejamientos = [[(1,2),(3,4),(5,6)],
[(1,5),(2,4),(3,6)],
[(1,6),(2,3),(4,5)],
[(1,3),(4,6),(2,5)]]
s=[1,0,0,0,0,0]
b=0.5
x=0.5
m=0.02
with open('salida.csv', 'wb') as csvfile:
writer = csv.DictWriter(csvfile,fieldnames = jugadores, delimiter=',',
quotechar='"', quoting=csv.QUOTE_MINIMAL)
writer.writeheader()
for _ in range(1000):
juego = Partida(jugadores, emparejamientos, senales, s, b, x, m)
juego.jugar()
for ronda in juego.memoria:
writer.writerow(ronda)
if name == 'main':
main()
This generates us a csv that opens with LibreOffice (to see more visually as the data remain) remains: In this case the csv has 6 columns (1 per player) and 4001 rows (the first is the header and the other 4000 corresponds to the thousand simulations of the 4 rounds game). To adapt it to other parameters you just have to modify them in the function main()There are many ways to do this, in this case I do what I do is that I keep on a list of dictionaries (self.memoria) the elections of each round and I wear the use to create the csv. To handle the csv itself I use the standard library https://docs.python.org/2/library/csv.html Python.Edition:If you want to get the frequencies with which each player displays each signal from csv You can do something like that:import collections
import csv
import itertools
with open('salida.csv', 'rb') as csvfile:
reader = csv.reader(csvfile, delimiter=',')
header = reader.next()
transpuesta = itertools.izip(*reader)
print 'Estadisticas:'
for n, jugador in enumerate(transpuesta):
print ' Jugador {0}:'.format(header[n])
t = len(jugador)*1.0
for (k,v) in collections.Counter(jugador).iteritems():
print " Senal {0} mostrada {1} veces. Frecuencia: {2}%".format(k, v, v/t*100)
csv.reader creates a generator that itera on the rows of csv, if you want to get the columns, a solution is to treat it as a matrix and use its transposed (delaying the first row that is the header with the names), for that we can use https://docs.python.org/2/library/itertools.html#itertools.izip . To count frequencies is very useful https://docs.python.org/2/library/collections.html#collections.Counter .This code can be used within the function main previous, for this moves the imports at the beginning of the module. An example output would be:Statistics:Player 1:Senal S3 shown 626 times. Frequency: 15.65%Senal S2 shown 626 times. Frequency: 15.65%Senal S1 shown 739 times. Frequency: 18.475%Senal S6 shown 663 times. Frequency: 16.575%Senal S5 shown 683 times. Frequency: 17.075%Senal S4 shown 663 times. Frequency: 16.575%Player 2:Senal S3 shown 692 times. Frequency: 17.3%Senal S2 shown 701 times. Frequency: 17.525%Senal S1 shown 693 times. Frequency: 17.325%Senal S6 shown 572 times. Frequency: 14.3%Senal S5 shown 687 times. Frequency: 17.175%Senal S4 shown 655 times. Frequency: 16.375%Player 3:Senal S3 shown 708 times. Frequency: 17.7%Senal S2 shown 730 times. Frequency: 18.25%Senal S1 shown 658 times. Frequency: 16.45%Senal S6 shown 652 times. Frequency: 16.3%Senal S5 shown 647 times. Frequency: 16.175%Senal S4 shown 605 times. Frequency: 15.125%Player 4:Senal S3 shown 696 times. Frequency: 17.4%Senal S2 shown 648 times. Frequency: 16.2%Senal S1 shown 685 times. Frequency: 17.125%Senal S6 shown 694 times. Frequency: 17.35%Senal S5 shown 639 times. Frequency: 15.975%Senal S4 shown 638 times. Frequency: 15.95%Player 5:Senal S3 shown 659 times. Frequency: 16.475%Senal S2 shown 594 times. Frequency: 14.85%Senal S1 shown 643 times. Frequency: 16.075%Senal S6 shown 686 times. Frequency: 17.15%Senal S5 shown 663 times. Frequency: 16.575%Senal S4 shown 755 times. Frequency: 18.875%Player 6:Senal S3 shown 553 times. Frequency: 13.825%Senal S2 shown 659 times. Frequency: 16.475%Senal S1 shown 672 times. Frequency: 16.8%Senal S6 shown 721 times. Frequency: 18.025%Senal S5 shown 681 times. Frequency: 17.025%Senal S4 shown 714 times. Frequency: 17.85% If you're going to work a lot with files csv and data I recommend that you look http://pandas.pydata.org/ Edition 2:I'll leave the code for you. main modified to generate csv you want according to the edition of your question. from random import random, sample
from bisect import bisect
import csv
class Partida():
def init(self, jugadores, emparejamientos, senales, s, b, x, m):
self.emparejamientos = emparejamientos
self.senales = senales
self.s = s
self.b = b
self.x = x
self.m = m
self.jugadores = {nombre: Partida.Jugador(senales)
for pareja in emparejamientos[0]
for nombre in pareja}
self.memoria = list()
def generar_senales(self):
def with_b(muestra, observa, s, r):
if not (muestra == observa == 0):
result = ((0.98) * (1.0 - self.b) * (1.0 - self.x) * muestra/r) + ((0.98) * (1.0 - self.b) * (self.x) * observa/r) + ((0.98) * self.b * s) + ((self.m / 8))
else:
result = ((0.98) * (1.0 - 0) * (1.0 - self.x) * muestra/r) + ((0.98) * (1.0 - 0) * (self.x) * observa/r) + ((0.98) * 0 * s) + ((self.m / 8))
return result
def choice(opciones, probs):
probAcumuladas = list()
aux = 0
for p in probs:
aux += p
probAcumuladas.append(aux)
r = random() * probAcumuladas[-1]
op = bisect(probAcumuladas, r)
return opciones[op]
yield dict(zip(self.jugadores.keys(), self.senales))
r = 1
while True:
eleccs = dict.fromkeys(self.jugadores.keys())
for nombre, inst in self.jugadores.items():
probs = [with_b(inst.mem_mostradas[op], inst.men_observadas[op], self.s[indx], r)
for indx, op in enumerate(self.senales)]
eleccs[nombre] = choice(self.senales, probs)
r += 1
yield eleccs
def jugar(self):
gen_sens = self.generar_senales()
for n, ronda in enumerate(self.emparejamientos):
senales = next(gen_sens)
self.memoria.append(senales)
for jugador1, jugador2 in ronda:
self.jugadores[jugador1].men_observadas[senales[jugador2]] += 1
self.jugadores[jugador2].men_observadas[senales[jugador1]] += 1
self.jugadores[jugador1].mem_mostradas[senales[jugador1]] += 1
self.jugadores[jugador2].mem_mostradas[senales[jugador2]] += 1
class Jugador():
def __init__(self, senales):
self.mem_mostradas = {senal: 0 for senal in senales}
self.men_observadas = {senal: 0 for senal in senales}
def main():
jugadores = [1, 2, 3, 4]
senales = ['S1', 'S2', 'S3', 'S4', ]
emparejamientos = [[(1,2),(3,4)],
[(1,3),(2,4)],
[(1,4),(2,3)]]
s=[1,0,0,0]
b=0.5
x=0.5
m=0.02
rondas = ['RONDA' + str(n+1) for n in range(len(emparejamientos))]
estadisticas = {jugador:{senal:[0 for ronda in rondas]
for senal in senales}
for jugador in jugadores}
for _ in range(1000):
juego = Partida(jugadores, emparejamientos, senales, s, b, x, m)
juego.jugar()
for n, ronda in enumerate(juego.memoria):
for jugador, senal in ronda.items():
estadisticas[jugador][senal][n] += 1
with open('salida.csv', 'wb') as csvfile:
writer =csv.writer(csvfile, delimiter=',',
quotechar='"', quoting=csv.QUOTE_MINIMAL)
writer.writerow(['JUGADOR', 'SENAL'] + rondas)
for jugador in jugadores:
for senal in senales:
writer.writerow([jugador, senal]+estadisticas[jugador][senal])
if name == 'main':
main()
Simulating your example we get a csv as follows: