#!/usr/bin/env python
# Test/CellFactory.py - Copyright rwa2
#
# This file was generated on %date% at %time%
#
# Parametric model of a pool of employees and employers who live at various transit-connected nodes
import psyco
psyco.log()
psyco.profile()
import string
from SimPy.Simulation import *
from SimPy.SimPlot import *
from random import *
from GeneralClasses import *
from TransportationInfrastructure import *
skillcode = {
1 : "description of jobcode 1",
2 : "description of jobcode 2",
3 : "description of jobcode 3"
}
class WorkShift:
"Hours and days worked"
def __init__(self, start_time, end_time, days, cycle):
self.st = start_time
self.et = end_time #
self.d = days # days which these times are in effect (for a 7day week, 0=mon, 1=tues, etc.)
self.c = cycle # days before schedule repeats (7 for a weekly schedule)
# List of exampe work schedules
WorkSchedule = [
WorkShift(9,17,range(5),7),
WorkShift(7,15,range(5),7),
WorkShift(16,0,range(5),7)
]
class Employee(Individual):
"A worker with skill codes capable of filling a job vacancy"
def __init__(self,parent):
Individual.__init__(self,parent)
self.skillset = [] # list of skillcodes this person possesses, really only just useful for distinguishing different kinds of work people mightdo
self.workloc = [] # list of VacancyPools, representing jobs this person has and their schedules
def live(self):
""""Do the things we do, over and over"""
global h2ts
global WorkSchedule
while True:
## self.sleep()
## self.commuteToWork()
## self.commuteHome()
## def commuteToWork(self):
"""Demand to go to work location"""
print "%7.4f %s : Going to work"%(now(),self.name)
commutetime = 60 # FIXME: assume we have a one hour commute for now
# Find next departure time for work referring to vacancypool
t=now()
cycle = WorkSchedule[self.workloc.schedule].c
t = t % (7 * 24 * h2ts) # weekly schedule repeats
for i in WorkSchedule[self.workloc.schedule].d: # find next workday
st = (WorkSchedule[self.workloc.schedule].st + (i * 24)) * h2ts
if t < st:
yield hold, self, st-t # leave for work
self.relocate(self.workloc.p)
print "%7.4f %s : At work"%(now(),self.name)
break
## def commuteHome(self):
"""Demand to return to home location"""
print "%7.4f %s : Going home"%(now(),self.name)
global h2ts
commutetime = 60 # FIXME: assume we have a one hour commute for now
# Find next departure time for work referring to vacancypool
global WorkSchedule
t=now()
cycle = WorkSchedule[self.workloc.schedule].c
t = t % (7 * 24 * h2ts) # weekly schedule repeats
for i in WorkSchedule[self.workloc.schedule].d: # find next workday
et = (WorkSchedule[self.workloc.schedule].et + (i * 24)) * h2ts
if t < et:
yield hold, self, et-t # leave for home
self.relocate(self.residence[0])
print "%7.4f %s : At home"%(now(),self.name)
break
class WorkShift:
"Hours and days worked"
def __init__(self, start_time, end_time, days, cycle):
self.st = start_time
self.et = end_time
self.d = days # days which these times are in effect (for a 7day week, 0=mon, 1=tues, etc.)
self.c = cycle # days before schedule repeats (7 for a weekly schedule)
# WorkSchedules assumes that the simulation always starts at midnight Monday morning.
WorkSchedule = [
WorkShift(9,17,range(5),7),
WorkShift(7,15,range(5),7),
WorkShift(16,0,range(5),7)
]
class VacancyPool:
"Job vacancies and shift schedule. Each group has the same job code and working schedule"
def __init__(self,parent,numPositions,skillcode,schedule):
self.p = parent # employer with these vacancies
self.n = numPositions # number of vacancies available
self.skillcode = skillcode # int index to a particular skill code
self.schedule = schedule # int index into the global WorkSchedule list
def createEmployees(self):
"""Create and returns an array of worker objects"""
peeps = []
for i in range(self.n): # TODO: - allow us to be understaffed
peeps.append(Employee(self.p)) # Create the employee, initially attach them to the employer object
peeps[i].skillset.append(self.skillcode) # Forcibly assume they already have the skills
# Give them a pointer to this vacancypool so they can look up where they work and when
peeps[i].workloc = self
return peeps
class Employer(Process,Cell):
"Workplace with a list of job vacancies with specific job skillcodes and shift times"
def __init__(self,parent,i):
Process.__init__(self,name='Emp'+str(i))
Cell.__init__(self,parent)
self.vp = [] # prepare a vacancy pool of job positions
def randomNode(cell):
""" Return a random subcell of the provided cell """
return cell.sc[randint(0,len(cell.sc)-1)]
def createEmployers(cell,numEmployers=1):
"Return an list of Employer objects with a distribution of jobcodes and schedules"
emp = []
for i in range(numEmployers):
##emp.append(Employer(name = "Emp%02d"%(i,)))
emp.append(Employer(cell,i))
emp[i].vp.append(VacancyPool(emp[i],10,skillcode=1,schedule=1))
print "Created employer ", emp[i].name
# Create array of workers to fill vacancies
workers = emp[i].vp[len(emp[i].vp)-1].createEmployees()
# Create homes at some node for those workers to live
global c
for w in workers:
w.getAHome(randomNode(c))
##emp[i].vp.append(VacancyPool(50,skillcode=2,schedule=2))
##emp[i].vp.append(VacancyPool(10,skillcode=3,schedule=2))
return (emp)
def model(SEED=101010):
"Initialize the scenario"
seed(SEED)
global c
c = Cell(None) # the master cell, has no parent "None"
for i in range(5): # create this many location nodes in the master cell
c.sc.append(Cell(c))
c.sc[i].sc.extend(createEmployers(c,randint(0,5))) # create employers distributed randomly across Cell nodes
# also loops through Employers and distribute Employee individuals across Cell nodes
# print what this looks like
##print c.printtree()
# create layers of transit infrastructure between Cell nodes
# simplest layer - direct src to dest for debuggins
# road layer - network of cars linked by geography, constrained by parametric congestion effects and parking lot sizes
# light rail layer - network of trains running fixed routes between stations
# bus layer - runs fixed routes / schedules on road networks through neighborhood Cells to link to light rail and other stops
# taxi / vanpool layer - runs between road-connected Cells as requested
# PRT layer - runs through neighborhood Cells on demand
# aircraft layer - runs between airport nodes
# water pipeline layer
# sewage pipeline layer
# electric grid layer
# information distribution layer: uni- and bi- directional
# set up simulation model and begin executing events
initialize()
for n in c.sc: # each node
for res in n.sc: # each ResidenceCell
if string.find(str(res),'ResidenceCell') > 0:
for p in res.sc: # each Individual
activate(p,p.live())
simulate(until=72*h2ts) #24 hours at a time scale of 1 minute
# export to schedule optimization engine, execute and read results
# simulate transit of vehicles
# add unexpected breakdowns / events and trigger a recalculation of schedule
# Run the model once with the default random seed
createTransitGraph(8)
model()
"""
# Plot monitored results
Histo = Mon.histogram(low=0.0,high=1400.0,nbins=20)
plt=SimPlot()
hst=plt.plotHistogram(Histo,xlab='Time (min)',
title = "Time spent sleeping",
color="red", width=2)
hst.postscr("sleeptime.ps")
plt.mainloop()
"""