123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742 |
- import sys
- sys.path.append("../../../src/")
- from infinity import *
- from DEVS import *
- import random
- north = 0
- east = 1
- south = 2
- west = 3
- vertical = "02"
- horizontal = "13"
- dir_to_int = {'n': north, 'e': east, 's': south, 'w': west}
- int_to_dir = {north: 'n', east: 'e', south: 's', west: 'w'}
- class Car:
- def __init__(self, ID, v, v_pref, dv_pos_max, dv_neg_max, departure_time):
- self.ID = ID
- self.v_pref = v_pref
- self.dv_pos_max = dv_pos_max
- self.dv_neg_max = dv_neg_max
- self.departure_time = departure_time
- self.distance_travelled = 0
- self.remaining_x = 0
- self.v = v
- def __eq__(self, other):
- return (self.ID == other.ID and
- self.v_pref == other.v_pref and
- self.dv_pos_max == other.dv_pos_max and
- self.dv_neg_max == other.dv_neg_max and
- self.departure_time == other.departure_time and
- self.distance_travelled == other.distance_travelled and
- self.remaining_x == other.remaining_x and
- self.v == other.v)
- def __str__(self):
- return "Car: ID = " + str(self.ID) + ", v_pref = " + str(self.v_pref) + ", dv_pos_max = " + str(self.dv_pos_max) + ", dv_neg_max = " + str(self.dv_neg_max) + ", departure_time = " + str(self.departure_time) + ", distance_travelled = " + str(self.distance_travelled) + (", v = %3f" % self.v) + ", path = " + str(self.path)
- def copy(self):
- car = Car(self.ID, self.v, self.v_pref, self.dv_pos_max, self.dv_neg_max, self.departure_time)
- car.distance_travelled = self.distance_travelled
- car.remaining_x = self.remaining_x
- car.path = list(self.path)
- return car
- class Query:
- def __init__(self, ID):
- self.ID = ID
- self.direction = ''
- def __str__(self):
- return "Query: ID = " + str(self.ID)
- def __eq__(self, other):
- return (self.ID == other.ID and self.direction == other.direction)
- def copy(self):
- query = Query(self.ID)
- query.direction = self.direction
- return query
- class QueryAck:
- def __init__(self, ID, t_until_dep):
- self.ID = ID
- self.t_until_dep = t_until_dep
- def __str__(self):
- return "Query Ack: ID = " + str(self.ID) + ", t_until_dep = %.3f" % self.t_until_dep
- def __eq__(self, other):
- return (self.ID == other.ID and self.t_until_dep == other.t_until_dep)
- def copy(self):
- return QueryAck(self.ID, self.t_until_dep)
- class BuildingState:
- def __init__(self, IAT_min, IAT_max, path, name):
- self.currentTime = 0
- from randomGenerator import RandomGenerator
- seed = random.random()
- self.randomGenerator = RandomGenerator(seed)
- self.send_query_delay = self.randomGenerator.uniform(IAT_min, IAT_max)
- self.send_car_delay = INFINITY
- self.path = path
- if path == []:
- self.send_query_delay = INFINITY
- self.name = name
- self.send_query_id = int(name.split("_", 1)[1].split("_")[0]) * 1000 + int(name.split("_", 1)[1].split("_")[1])
- self.send_car_id = self.send_query_id
- self.next_v_pref = 0
- self.sent = 0
- def copy(self):
- new = BuildingState(0, 0, list(self.path), self.name)
- new.currentTime = self.currentTime
- new.send_query_delay = self.send_query_delay
- new.send_car_delay = self.send_car_delay
- new.send_query_id = self.send_query_id
- new.send_car_id = self.send_car_id
- new.next_v_pref = self.next_v_pref
- new.randomGenerator = self.randomGenerator.copy()
- new.sent = self.sent
- return new
- def __str__(self):
- if self.path != []:
- return "Residence: send_query_delay = %.3f, send_query_id = %s, send_car_delay = %.3f, send_car_id = %s" % (self.send_query_delay, self.send_query_id, self.send_car_delay, self.send_car_id)
- else:
- return "Commercial: waiting..."
- class Building(AtomicDEVS):
- def __init__(self, generator, district, path = [], IAT_min = 100, IAT_max = 100, v_pref_min = 15, v_pref_max = 15, dv_pos_max = 15, dv_neg_max = 150, name="Building"):
- # parent class constructor
- AtomicDEVS.__init__(self, name)
- # copy of arguments
- self.IAT_min = IAT_min
- self.IAT_max = IAT_max
- self.v_pref_min = v_pref_min
- self.v_pref_max = v_pref_max
- self.dv_pos_max = dv_pos_max
- self.dv_neg_max = dv_neg_max
- # output ports
- self.q_sans = self.addOutPort(name="q_sans")
- self.q_send = self.addOutPort(name="q_send")
- self.exit = self.addOutPort(name="exit")
- self.Q_send = self.q_send
- self.car_out = self.exit
- # input ports
- self.q_rans = self.addInPort(name="q_rans")
- #self.q_recv = self.addInPort(name="q_recv")
- self.Q_rack = self.q_rans
- self.entry = self.addInPort(name="entry")
- # set the state
- self.state = BuildingState(IAT_min, IAT_max, path, name)
- self.state.next_v_pref = self.state.randomGenerator.uniform(self.v_pref_min, self.v_pref_max)
- self.send_max = 1
- self.district = district
- def intTransition(self):
- mintime = self.timeAdvance()
- #print("Got mintime: " + str(mintime))
- self.state.currentTime += mintime
- self.state.send_query_delay -= mintime
- self.state.send_car_delay -= mintime
- if self.state.send_car_delay == 0:
- self.state.send_car_delay = INFINITY
- self.state.send_car_id = self.state.send_query_id
- self.state.next_v_pref = self.state.randomGenerator.uniform(self.v_pref_min, self.v_pref_max)
- elif self.state.send_query_delay == 0:
- self.state.send_query_delay = INFINITY
- return self.state
-
- def outputFnc(self):
- mintime = self.timeAdvance()
- #print("Got mintime: " + str(mintime))
- currentTime = self.state.currentTime + self.timeAdvance()
- outputs = {}
- if self.state.send_car_delay == mintime:
- v_pref = self.state.next_v_pref
- car = Car(self.state.send_car_id, 0, v_pref, self.dv_pos_max, self.dv_neg_max, currentTime)
- car.path = self.state.path
- #self.poke(self.car_out, car)
- outputs[self.car_out] = [car]
- elif self.state.send_query_delay == mintime:
- query = Query(self.state.send_query_id)
- #self.poke(self.Q_send, query)
- outputs[self.Q_send] = [query]
- return outputs
-
- def timeAdvance(self):
- return min(self.state.send_query_delay, self.state.send_car_delay)
- def extTransition(self, inputs):
- #print("ELAPSED: " + str(self.elapsed))
- #print("Got elapsed: " + str(self.elapsed))
- self.state.currentTime += self.elapsed
- self.state.send_query_delay -= self.elapsed
- self.state.send_car_delay -= self.elapsed
- queryAcks = inputs.get(self.Q_rack, [])
- for queryAck in queryAcks:
- if self.state.send_car_id == queryAck.ID and (self.state.sent < self.send_max):
- self.state.send_car_delay = queryAck.t_until_dep
- if queryAck.t_until_dep < 20000:
- self.state.sent += 1
- # Generate the next situation
- if self.state.sent < self.send_max:
- self.state.send_query_delay = self.randomGenerator.uniform(self.IAT_min, self.IAT_max)
- #self.state.send_query_id = int(self.randomGenerator.uniform(0, 100000))
- self.state.send_query_id += 1000000
- return self.state
- class Residence(Building):
- def __init__(self, path, district, name = "Residence", IAT_min = 100, IAT_max = 100, v_pref_min = 15, v_pref_max = 15, dv_pos_max = 15, dv_neg_max = 15):
- Building.__init__(self, True, district, path=path, name=name)
- class CommercialState(object):
- def __init__(self, car):
- self.car = car
- def __str__(self):
- return "CommercialState"
- def copy(self):
- return CommercialState(self.car)
- class Commercial(Building):
- def __init__(self, district, name="Commercial"):
- Building.__init__(self, False, district, name=name)
- self.state = CommercialState(None)
- self.toCollector = self.addOutPort(name="toCollector")
- def extTransition(self, inputs):
- return CommercialState(inputs[self.entry][0])
- def intTransition(self):
- return CommercialState(None)
- def outputFnc(self):
- return {self.toCollector: [self.state.car]}
- def timeAdvance(self):
- if self.state.car is None:
- return INFINITY
- else:
- return 0.0
-
- class RoadSegmentState():
- def __init__(self):
- self.cars_present = []
- self.query_buffer = []
- self.deny_list = []
- self.reserved = False
- self.send_query_delay = INFINITY
- self.send_query_id = None
- self.send_ack_delay = INFINITY
- self.send_ack_id = None
- self.send_car_delay = INFINITY
- self.send_car_id = None
- self.last_car = None
- def __eq__(self, other):
- if self.query_buffer != other.query_buffer:
- return False
- if not (self.send_query_delay == other.send_query_delay and
- self.send_ack_delay == other.send_ack_delay and
- self.send_car_delay == other.send_car_delay and
- self.send_query_id == other.send_query_id and
- self.send_ack_id == other.send_ack_id and
- self.send_car_id == other.send_car_id):
- return False
- if self.reserved != other.reserved:
- return False
- if len(self.cars_present) != len(other.cars_present):
- return False
- for c1, c2 in zip(self.cars_present, other.cars_present):
- if c1 != c2:
- return False
- if self.last_car != other.last_car:
- return False
- if len(self.deny_list) != len(other.deny_list):
- return False
- for q1, q2 in zip(self.deny_list, other.deny_list):
- if q1 != q2:
- return False
- return True
- def copy(self):
- new = RoadSegmentState()
- new.cars_present = [c.copy() for c in self.cars_present]
- new.deny_list = [q.copy() for q in self.deny_list]
- new.query_buffer = list(self.query_buffer)
- new.reserved = self.reserved
- new.send_query_delay = self.send_query_delay
- new.send_query_id = self.send_query_id
- new.send_ack_delay = self.send_ack_delay
- new.send_ack_id = self.send_ack_id
- new.send_car_delay = self.send_car_delay
- new.send_car_id = self.send_car_id
- new.last_car = self.last_car
- return new
- def __str__(self):
- string = "Road segment: cars_present = ["
- for i in self.cars_present:
- string += str(i.ID) + ", "
- return string + "] , send_query_delay = %.3f, send_ack_delay = %.3f, send_car_delay = %.3f, send_ack_id = %s" % (self.send_query_delay, self.send_ack_delay, self.send_car_delay, self.send_ack_id)
- class RoadSegment(AtomicDEVS):
- def __init__(self, district, load, l = 100.0, v_max = 18.0, observ_delay = 0.1, name = "RoadSegment"):
- AtomicDEVS.__init__(self, name)
- # arguments
- self.l = float(l)
- self.v_max = v_max
- self.observ_delay = observ_delay
- self.district = district
- self.load = load
- # in-ports
- self.q_rans = self.addInPort(name="q_rans")
- self.q_recv = self.addInPort(name="q_recv")
- self.car_in = self.addInPort(name="car_in")
- self.entries = self.addInPort(name="entries")
- self.q_rans_bs = self.addInPort(name="q_rans_bs")
- self.q_recv_bs = self.addInPort(name="q_recv_bs")
- # compatibility bindings...
- self.Q_recv = self.q_recv
- self.Q_rack = self.q_rans
- # out-ports
- self.q_sans = self.addOutPort(name="q_sans")
- self.q_send = self.addOutPort(name="q_send")
- self.car_out = self.addOutPort(name="car_out")
- self.exits = self.addOutPort(name="exits")
- self.q_sans_bs = self.addOutPort(name="q_sans_bs")
- # compatibility bindings...
- self.Q_send = self.q_send
- self.Q_sack = self.q_sans
- self.state = RoadSegmentState()
- def extTransition(self, inputs):
- queries = inputs.get(self.Q_recv, [])
- queries.extend(inputs.get(self.q_recv_bs, []))
- cars = inputs.get(self.car_in, [])
- cars.extend(inputs.get(self.entries, []))
- acks = inputs.get(self.Q_rack, [])
- acks.extend(inputs.get(self.q_rans_bs, []))
- self.state.send_query_delay -= self.elapsed
- self.state.send_ack_delay -= self.elapsed
- self.state.send_car_delay -= self.elapsed
- for query in queries:
- if (not self.state.reserved) and not (len(self.state.cars_present) > 1 or (len(self.state.cars_present) == 1 and self.state.cars_present[0].v == 0)):
- self.state.send_ack_delay = self.observ_delay
- self.state.send_ack_id = query.ID
- self.state.reserved = True
- else:
- self.state.query_buffer.append(query.ID)
- self.state.deny_list.append(query)
- if self.state.send_ack_delay == INFINITY:
- self.state.send_ack_delay = self.observ_delay
- self.state.send_ack_id = query.ID
- self.state.last_car = query.ID
- for car in self.state.cars_present:
- car.remaining_x -= self.elapsed * car.v
- for car in cars:
- self.state.last_car = None
- car.remaining_x = self.l
- self.state.cars_present.append(car)
- if len(self.state.cars_present) != 1:
- for other_car in self.state.cars_present:
- other_car.v = 0
- self.state.send_query_delay = INFINITY
- self.state.send_ack_delay = INFINITY
- self.state.send_car_delay = INFINITY
- else:
- self.state.send_query_delay = 0
- self.state.send_query_id = car.ID
- if self.state.cars_present[-1].v == 0:
- t_to_dep = INFINITY
- else:
- t_to_dep = max(0, self.l/self.state.cars_present[-1].v)
- self.state.send_car_delay = t_to_dep
- self.state.send_car_id = car.ID
- for ack in acks:
- if (len(self.state.cars_present) == 1) and (ack.ID == self.state.cars_present[0].ID):
- car = self.state.cars_present[0]
- t_no_col = ack.t_until_dep
- v_old = car.v
- v_pref = car.v_pref
- remaining_x = car.remaining_x
- if t_no_col + 1 == t_no_col:
- v_new = 0
- t_until_dep = INFINITY
- else:
- v_ideal = remaining_x / max(t_no_col, remaining_x / min(v_pref, self.v_max))
- diff = v_ideal - v_old
- if diff < 0:
- if -diff > car.dv_neg_max:
- diff = -car.dv_neg_max
- elif diff > 0:
- if diff > car.dv_pos_max:
- diff = car.dv_pos_max
- v_new = v_old + diff
- if v_new == 0:
- t_until_dep = INFINITY
- else:
- t_until_dep = car.remaining_x / v_new
-
- car.v = v_new
- t_until_dep = max(0, t_until_dep)
- if t_until_dep > self.state.send_car_delay and self.state.last_car is not None:
- self.state.send_ack_delay = self.observ_delay
- self.state.send_ack_id = self.state.last_car
- self.state.send_car_delay = t_until_dep
- self.state.send_car_id = ack.ID
- if t_until_dep == INFINITY:
- self.state.send_query_id = ack.ID
- else:
- self.state.send_query_id = None
- self.state.send_query_delay = INFINITY
- return self.state
- def intTransition(self):
- for _ in range(self.load):
- pass
- mintime = self.mintime()
- self.state.send_query_delay -= mintime
- self.state.send_ack_delay -= mintime
- self.state.send_car_delay -= mintime
- if self.state.send_ack_delay == 0:
- self.state.send_ack_delay = INFINITY
- self.state.send_ack_id = None
- elif self.state.send_query_delay == 0:
- # Just sent a query, now deny all other queries and wait until the current car has left
- self.state.send_query_delay = INFINITY
- self.state.send_query_id = None
- elif self.state.send_car_delay == 0:
- self.state.cars_present = []
- self.state.send_car_delay = INFINITY
- self.state.send_car_id = None
- # A car has left, so we can answer to the first other query we received
- if len(self.state.query_buffer) != 0:
- self.state.send_ack_delay = self.observ_delay
- #print("Setting %s in %s" % (self.state.query_buffer, self.name))
- self.state.send_ack_id = self.state.query_buffer.pop()
- else:
- # No car is waiting for this segment, so 'unreserve' it
- self.state.reserved = False
- if self.state.send_ack_id == None and len(self.state.deny_list) > 0:
- self.state.send_ack_delay = self.observ_delay
- #print("Denylist = %s in %s" % (self.state.deny_list, self.name))
- self.state.send_ack_id = self.state.deny_list[0].ID
- self.state.deny_list = self.state.deny_list[1:]
- return self.state
- def outputFnc(self):
- outputs = {}
- mintime = self.mintime()
- if self.state.send_ack_delay == mintime:
- ackID = self.state.send_ack_id
- if len(self.state.cars_present) == 0:
- t_until_dep = 0
- elif (self.state.cars_present[0].v) == 0:
- t_until_dep = INFINITY
- else:
- t_until_dep = self.l / self.state.cars_present[0].v
- ack = QueryAck(ackID, t_until_dep)
- outputs[self.Q_sack] = [ack]
- outputs[self.q_sans_bs] = [ack]
- elif self.state.send_query_delay == mintime:
- query = Query(self.state.send_query_id)
- if self.state.cars_present[0].path != []:
- query.direction = self.state.cars_present[0].path[0]
- outputs[self.Q_send] = [query]
- elif self.state.send_car_delay == mintime:
- car = self.state.cars_present[0]
- car.distance_travelled += self.l
- if len(car.path) == 0:
- outputs[self.exits] = [car]
- else:
- outputs[self.car_out] = [car]
- return outputs
- def mintime(self):
- return min(self.state.send_query_delay, self.state.send_ack_delay, self.state.send_car_delay)
- def timeAdvance(self):
- #return min(self.state.send_query_delay, self.state.send_ack_delay, self.state.send_car_delay)
- delay = min(self.state.send_query_delay, self.state.send_ack_delay, self.state.send_car_delay)
- # Take care of floating point errors
- return max(delay, 0)
- class Road(CoupledDEVS):
- def __init__(self, district, load, name="Road", segments=5):
- CoupledDEVS.__init__(self, name)
- self.segment = []
- for i in range(segments):
- self.segment.append(self.addSubModel(RoadSegment(load=load, district=district, name=(name + "_" + str(i)))))
- # in-ports
- self.q_rans = self.addInPort(name="q_rans")
- self.q_recv = self.addInPort(name="q_recv")
- self.car_in = self.addInPort(name="car_in")
- self.entries = self.addInPort(name="entries")
- self.q_rans_bs = self.addInPort(name="q_rans_bs")
- self.q_recv_bs = self.addInPort(name="q_recv_bs")
- # out-ports
- self.q_sans = self.addOutPort(name="q_sans")
- self.q_send = self.addOutPort(name="q_send")
- self.car_out = self.addOutPort(name="car_out")
- self.exits = self.addOutPort(name="exits")
- self.q_sans_bs = self.addOutPort(name="q_sans_bs")
- self.connectPorts(self.q_rans, self.segment[-1].q_rans)
- self.connectPorts(self.q_recv, self.segment[0].q_recv)
- self.connectPorts(self.car_in, self.segment[0].car_in)
- self.connectPorts(self.entries, self.segment[0].entries)
- self.connectPorts(self.q_rans_bs, self.segment[0].q_rans_bs)
- self.connectPorts(self.q_recv_bs, self.segment[0].q_recv_bs)
- self.connectPorts(self.segment[0].q_sans, self.q_sans)
- self.connectPorts(self.segment[-1].q_send, self.q_send)
- self.connectPorts(self.segment[-1].car_out, self.car_out)
- self.connectPorts(self.segment[0].exits, self.exits)
- self.connectPorts(self.segment[0].q_sans_bs, self.q_sans_bs)
- for i in range(segments):
- if i == 0:
- continue
- self.connectPorts(self.segment[i].q_sans, self.segment[i-1].q_rans)
- self.connectPorts(self.segment[i-1].q_send, self.segment[i].q_recv)
- self.connectPorts(self.segment[i-1].car_out, self.segment[i].car_in)
- class IntersectionState():
- def __init__(self, switch_signal):
- self.send_query = []
- self.send_ack = []
- self.send_car = []
- self.queued_queries = []
- self.id_locations = [None, None, None, None]
- self.block = vertical
- self.switch_signal = switch_signal
- self.ackDir = {}
- def __str__(self):
- return "ISECT blocking " + str(self.block)
- return "Intersection: send_query = " + str(self.send_query) + ", send_ack = " + str(self.send_ack) + ", send_car = " + str(self.send_car) + ", block = " + str(self.block)
- def copy(self):
- new = IntersectionState(self.switch_signal)
- new.send_query = [q.copy() for q in self.send_query]
- new.send_ack = [a.copy() for a in self.send_ack]
- new.send_car = [c.copy() for c in self.send_car]
- new.queued_queries = [q.copy() for q in self.queued_queries]
- new.id_locations = list(self.id_locations)
- new.block = self.block
- new.switch_signal = self.switch_signal
- new.ackDir = dict(self.ackDir)
- return new
- class Intersection(AtomicDEVS):
- def __init__(self, district, name="Intersection", switch_signal = 30):
- AtomicDEVS.__init__(self, name=name)
- self.state = IntersectionState(switch_signal)
- self.switch_signal_delay = switch_signal
- self.district = district
- self.q_send = []
- self.q_send.append(self.addOutPort(name="q_send_to_n"))
- self.q_send.append(self.addOutPort(name="q_send_to_e"))
- self.q_send.append(self.addOutPort(name="q_send_to_s"))
- self.q_send.append(self.addOutPort(name="q_send_to_w"))
- self.q_rans = []
- self.q_rans.append(self.addInPort(name="q_rans_from_n"))
- self.q_rans.append(self.addInPort(name="q_rans_from_e"))
- self.q_rans.append(self.addInPort(name="q_rans_from_s"))
- self.q_rans.append(self.addInPort(name="q_rans_from_w"))
- self.q_recv = []
- self.q_recv.append(self.addInPort(name="q_recv_from_n"))
- self.q_recv.append(self.addInPort(name="q_recv_from_e"))
- self.q_recv.append(self.addInPort(name="q_recv_from_s"))
- self.q_recv.append(self.addInPort(name="q_recv_from_w"))
- self.q_sans = []
- self.q_sans.append(self.addOutPort(name="q_sans_to_n"))
- self.q_sans.append(self.addOutPort(name="q_sans_to_e"))
- self.q_sans.append(self.addOutPort(name="q_sans_to_s"))
- self.q_sans.append(self.addOutPort(name="q_sans_to_w"))
- self.car_in = []
- self.car_in.append(self.addInPort(name="car_in_from_n"))
- self.car_in.append(self.addInPort(name="car_in_from_e"))
- self.car_in.append(self.addInPort(name="car_in_from_s"))
- self.car_in.append(self.addInPort(name="car_in_from_w"))
- self.car_out = []
- self.car_out.append(self.addOutPort(name="car_out_to_n"))
- self.car_out.append(self.addOutPort(name="car_out_to_e"))
- self.car_out.append(self.addOutPort(name="car_out_to_s"))
- self.car_out.append(self.addOutPort(name="car_out_to_w"))
- def intTransition(self):
- self.state.switch_signal -= self.timeAdvance()
- if self.state.switch_signal <= 1e-6:
- # We switched our traffic lights
- self.state.switch_signal = self.switch_signal_delay
- self.state.queued_queries = []
- self.state.block = vertical if self.state.block == horizontal else horizontal
- for loc, car_id in enumerate(self.state.id_locations):
- # Notify all cars that got 'green' that they should not continue
- if car_id is None:
- continue
- try:
- if str(loc) in self.state.block:
- query = Query(car_id)
- query.direction = int_to_dir[self.state.ackDir[car_id]]
- self.state.queued_queries.append(query)
- except KeyError:
- pass
- self.state.send_car = []
- self.state.send_query = []
- self.state.send_ack = []
- return self.state
- def extTransition(self, inputs):
- # Simple forwarding of all messages
- # Unless the direction in which it is going is blocked
- self.state.switch_signal -= self.elapsed
- for direction in range(4):
- blocked = str(direction) in self.state.block
- for car in inputs.get(self.car_in[direction], []):
- self.state.send_car.append(car)
- # Got a car, so remove its ID location entry
- try:
- del self.state.ackDir[car.ID]
- self.state.id_locations[self.state.id_locations.index(car.ID)] = None
- except (KeyError, ValueError):
- pass
- self.state.queued_queries = [query for query in self.state.queued_queries if query.ID != car.ID]
- for query in inputs.get(self.q_recv[direction], []):
- self.state.id_locations[direction] = query.ID
- self.state.ackDir[query.ID] = dir_to_int[query.direction]
- if blocked:
- self.state.send_ack.append(QueryAck(query.ID, INFINITY))
- self.state.queued_queries.append(query)
- else:
- self.state.send_query.append(query)
- for ack in inputs.get(self.q_rans[direction], []):
- self.state.ackDir[ack.ID] = direction
- if (ack.t_until_dep > self.state.switch_signal) or ((ack.ID in self.state.id_locations) and (str(self.state.id_locations.index(ack.ID)) in self.state.block)):
- try:
- self.state.id_locations.index(ack.ID)
- t_until_dep = INFINITY
- nquery = Query(ack.ID)
- nquery.direction = int_to_dir[direction]
- self.state.queued_queries.append(nquery)
- except ValueError:
- continue
- else:
- t_until_dep = ack.t_until_dep
- self.state.send_ack.append(QueryAck(ack.ID, t_until_dep))
- return self.state
- def outputFnc(self):
- # Can simply overwrite, as multiple calls to the same destination is impossible
- toSend = {}
- new_block = vertical if self.state.block == horizontal else horizontal
- if self.state.switch_signal == self.timeAdvance():
- # We switch our traffic lights
- # Resend all queries for those that are waiting
- for query in self.state.queued_queries:
- if str(self.state.id_locations.index(query.ID)) not in new_block:
- toSend[self.q_send[dir_to_int[query.direction]]] = [query]
- for loc, car_id in enumerate(self.state.id_locations):
- # Notify all cars that got 'green' that they should not continue
- if car_id is None:
- continue
- if str(loc) in new_block:
- toSend[self.q_sans[loc]] = [QueryAck(car_id, INFINITY)]
- else:
- try:
- query = Query(car_id)
- query.direction = int_to_dir[self.state.ackDir[car_id]]
- toSend[self.q_send[self.state.ackDir[car_id]]] = [query]
- except KeyError:
- pass
- # We might have some messages to forward too
- for car in self.state.send_car:
- dest = car.path.pop(0)
- toSend[self.car_out[dir_to_int[dest]]] = [car]
- for query in self.state.send_query:
- toSend[self.q_send[dir_to_int[query.direction]]] = [query]
- for ack in self.state.send_ack:
- # Broadcast for now
- try:
- toSend[self.q_sans[self.state.id_locations.index(ack.ID)]] = [ack]
- except ValueError:
- pass
- return toSend
- def timeAdvance(self):
- if len(self.state.send_car) + len(self.state.send_query) + len(self.state.send_ack) > 0:
- return 0.0
- else:
- return max(self.state.switch_signal, 0.0)
- class CollectorState(object):
- def __init__(self):
- self.cars = []
- def copy(self):
- new = CollectorState()
- new.cars = list(self.cars)
- return new
- def __str__(self):
- ## Print your statistics here!
- s = "All cars collected:"
- for car in self.cars:
- s += "\n\t\t\t%s" % car
- return s
- class Collector(AtomicDEVS):
- def __init__(self):
- AtomicDEVS.__init__(self, "Collector")
- self.car_in = self.addInPort("car_in")
- self.state = CollectorState()
- self.district = 0
- def extTransition(self, inputs):
- self.state.cars.extend(inputs[self.car_in])
- return self.state
|