Created
July 9, 2014 16:38
-
-
Save niklasf/03bc286211c3a7f87383 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python2 | |
import random | |
import math | |
# Model | |
# ===== | |
class TicTacToeGrid(object): | |
def __init__(self): | |
# The world - namely the tic-tac-toe grid - has 9 cells, | |
# each of which can be either " ", "X" or "O". | |
self.cells = [" ", " ", " ", | |
" ", " ", " ", | |
" ", " ", " "] | |
def __str__(self): | |
return (" " + self.cells[0] + " | " + self.cells[1] + " | " + self.cells[2] + "\n" + | |
"---|---|---\n" + | |
" " + self.cells[3] + " | " + self.cells[4] + " | " + self.cells[5] + "\n" + | |
"---|---|---\n" + | |
" " + self.cells[6] + " | " + self.cells[7] + " | " + self.cells[8]) | |
def tick(self): | |
# The world does not do anything by itself. | |
pass | |
def sync(self, grids): | |
# When merging different grids, the one with the least empty cells | |
# is the right one. | |
self.cells = min(grids, key=lambda grid: grid.cells.count(" ")).cells | |
class AgentX(object): | |
def tick(self): | |
# Is it my turn? | |
if grid.cells.count("X") <= grid.cells.count("O"): | |
# Select a cell and mark if empty. | |
cell = random.randint(0, 8) | |
if grid.cells[cell] == " ": | |
grid.cells[cell] = "X" | |
class AgentO(object): | |
def tick(self): | |
# Is it my turn? | |
if grid.cells.count("O") < grid.cells.count("X"): | |
# Select a cell and mark if empty. | |
cell = random.randint(0, 8) | |
if grid.cells[cell] == " ": | |
grid.cells[cell] = "O" | |
# Initialisation: Create the objects. | |
grid = TicTacToeGrid() | |
agentx = AgentX() | |
agento = AgentO() | |
sync_objects = [ grid ] | |
non_sync_objects = [ agentx, agento ] | |
# Simulation | |
# ========== | |
from mpi4py import MPI | |
core_id = MPI.COMM_WORLD.Get_rank() | |
cores = MPI.COMM_WORLD.Get_size() | |
# Randomly group non-synchronized objects like [o1, o2, ...] for example as | |
# [[o4, o3], [o1, o2], ...] to scatter across cores. | |
random.shuffle(non_sync_objects) | |
objects_per_core = int(math.ceil(float(len(non_sync_objects)) / cores)) | |
groups = [non_sync_objects[i:i+objects_per_core] for i in range(0, len(non_sync_objects), objects_per_core)] | |
# Fix luxury problem: If more cores than objects, some empty groups are needed. | |
while len(groups) < cores: | |
groups += [[]] | |
local_non_sync_objects = MPI.COMM_WORLD.scatter(groups) | |
# Simulate a few ticks. | |
for tick in xrange(0, 10): | |
# Debug output (only on core 0 to avoid mixed outputs). | |
if core_id == 0: | |
print "Tick: %s" % (tick, ) | |
print grid | |
print "----------------------------------------------------" | |
# Go through all synchronized objects. | |
for instance in sync_objects: | |
# Gather all instances from the other cores. | |
instances = MPI.COMM_WORLD.allgather(instance) | |
# Let each instance synchronize itself with instances from the other | |
# cores. | |
instance.sync(instances) | |
# Execute tick for all synchronized objects. | |
for sync_object in sync_objects: | |
sync_object.tick() | |
# Execute tick for all non synchronized objects. | |
for local_non_sync_object in local_non_sync_objects: | |
local_non_sync_object.tick() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment