Beispiel #1
0
    def __init__(self, *args, **kwargs):
        super(GasStation, self).__init__(*args, **kwargs)
        config = self.env.config
        self.add_connections('tanker_company')
        self.arrival_interval = config.get('gas_station.arrival_interval', 60)

        station_capacity = config.get('gas_station.capacity', 200)
        self.reservoir = Container(self.env,
                                   capacity=station_capacity,
                                   init=station_capacity)
        self.auto_probe('reservoir', log={})

        self.threshold_pct = config.get('gas_station.threshold_pct', 10)

        self.pump_rate = config.get('gas_station.pump_rate', 2)
        num_pumps = config.get('gas_station.pumps', 2)
        self.fuel_pumps = Resource(self.env, capacity=num_pumps)
        self.auto_probe('fuel_pumps', log={})

        self.car_capacity = config.get('car.capacity', 50)
        self.car_level_range = config.get('car.level', [5, 25])

        # A gas station has two persistent processes. One to monitor the
        # reservoir level and one that models the arrival of cars at the
        # station. Desmod starts these processes before simulation phase.
        self.add_processes(self._monitor_reservoir, self._traffic_generator)
Beispiel #2
0
def cross_sim():
    """
    cross module test: Cross 模块测试单元
    """
    env = Environment()
    INPUT_QUEUE_ID.extend(
        [''.join([MACHINE_ID, '_in', str(i)]) for i in range(NUM_PORT_IN)]
    )
    OUTPUT_QUEUE_ID.extend(
        [''.join([MACHINE_ID, '_out', str(i)]) for i in range(NUM_PORT_OUT)]
    )

    for id in INPUT_QUEUE_ID:
        INPUT_QUEUE_DIC.update({id: PriorityStore(env=env)})
    for id in OUTPUT_QUEUE_ID:
        OUTPUT_QUEUE_DIC.update({id: PriorityStore(env=env)})

    generator_queue_res = Resource(env=env, capacity=QUEUE_RES)
    generator_package_res = Resource(env=env, capacity=PACKAGE_RES)

    packages(env=env,
             generator_package_res=generator_package_res,
             generator_queue_res=generator_queue_res)
    hospital = Hospital(env=env,id_h=MACHINE_ID,
                        hospital_capacity=NUM_PEOPLE,
                        input_dic=INPUT_QUEUE_DIC,
                        output_dic=OUTPUT_QUEUE_DIC)
    env.run()
Beispiel #3
0
    def __init__(self, data_series: EventSeries, pkg_process_delay: int = 0, **kwargs):
        self.pkg_process_delay = pkg_process_delay
        self.data_series = data_series

        super().__init__(**kwargs)

        self.link_queues = {}
        self.router_queues = {}
        for router_id in self.conn_graph.nodes:
            self.link_queues[router_id] = {}
            for _, nbr in self.conn_graph.edges(router_id):
                self.link_queues[router_id][nbr] = Resource(self.env, capacity=1)
            self.router_queues[router_id] = Resource(self.env, capacity=1)
Beispiel #4
0
    def __init__(self, env: Environment, name: str, block_capacity=float("inf")):
        self.name = name
        self.env: Environment = env
        self.overall_count_in = 0
        on_enter_or_exit_method_callable = Callable[
            [Entity, Optional[Block], Optional[Block]], None
        ]
        self.do_on_enter_list: List[on_enter_or_exit_method_callable] = []
        self.do_on_exit_list: List[on_enter_or_exit_method_callable] = []
        self.entities: List[Entity] = []
        self.successors: List[Block] = []
        self.block_resource = Resource(env=env, capacity=block_capacity)
        self.state_manager = StateManager(self.on_block_state_change)

        self.env.process(self.late_state_evaluation())
Beispiel #5
0
    def __init__(self, *args, **kwargs):
        super(GasStation, self).__init__(*args, **kwargs)
        config = self.env.config
        self.add_connections('tanker_company')
        self.arrival_interval = config.get('gas_station.arrival_interval', 60)

        station_capacity = config.get('gas_station.capacity', 200)
        self.reservoir = Container(self.env,
                                   capacity=station_capacity,
                                   init=station_capacity)
        self.auto_probe('reservoir', log={})

        self.threshold_pct = config.get('gas_station.threshold_pct', 10)

        self.pump_rate = config.get('gas_station.pump_rate', 2)
        num_pumps = config.get('gas_station.pumps', 2)
        self.fuel_pumps = Resource(self.env, capacity=num_pumps)
        self.auto_probe('fuel_pumps', log={})

        self.car_capacity = config.get('car.capacity', 50)
        self.car_level_range = config.get('car.level', [5, 25])

        # A gas station has two persistent processes. One to monitor the
        # reservoir level and one that models the arrival of cars at the
        # station. Desmod starts these processes before simulation phase.
        self.add_processes(self._monitor_reservoir, self._traffic_generator)
Beispiel #6
0
 def create(self, env: Environment,
            fn: FunctionContainer) -> FunctionSimulator:
     workers = int(fn.labels['workers'])
     queue = Resource(env=env, capacity=workers)
     return InterferenceAwarePythonHttpSimulator(
         queue, linear_queue_fet_increase, fn,
         self.fn_characterizations[fn.image])
 def __init__(self, env):
     self.env = env
     self.generator_process = env.process(self.generate_request(env))
     self.resource_list = [
         Resource(env, capacity=1)
         for _ in range(defines.CHARGING_STATIONS_COUNT)
     ]
 def create(self, env: Environment,
            fn: FunctionDefinition) -> FunctionSimulator:
     workers = int(fn.labels['workers'])
     queue = Resource(env=env, capacity=workers)
     return InterferenceAwarePythonHttpSimulator(queue,
                                                 linear_queue_fet_increase,
                                                 fn)
Beispiel #9
0
    def __init__(self,
                 env,
                 duration,
                 inspectors=float('inf'),
                 officers=float('inf'),
                 budget=float('inf'),
                 max_loan=float('inf'),
                 min_credit=0,
                 debt_income_ratio=0.2,
                 loan_term=30.0,
                 interest_rate=0.04,
                 declaration=0,
                 deadline=60):
        """Initiate SBA real property loan recovery program.

        Keyword Arguments:
        env -- simpy.Envionment() object
        duration -- io.ProbabilityDistribution() object
        inspectors -- Integer, indicating number of building inspectors assigned to the programs
        officers -- Number of program staff that reviews and approves loan applications
        budget -- Integer or float, indicating the initial budget available from
                    the recovery program.
        max_loan -- The maximum amount ($) of loan that any one entity can receive
        debt_income_ratio -- Monthly SBA loan payment / entity income ; used to estimate
                                loan amount.
        min_credit -- A FICO-like credit score used as threshold for approving loan.
        declaration -- A value indicating how many days after the event
                                a federal disaster was declared.
        deadline -- A value indicating how many days after the
                                federal disaster declaration was made the applications
                                must be submitted.

        """
        FinancialRecoveryProgram.__init__(self, env, duration, budget)

        # Define staff/personnel specific to this class
        self.officers = Resource(self.env, capacity=officers)
        self.inspectors = Resource(self.env, capacity=inspectors)

        # New attributes
        self.min_credit = min_credit
        self.debt_income_ratio = debt_income_ratio
        self.loan_term = loan_term  # years
        self.max_loan = max_loan
        self.interest_rate = interest_rate  # annual rate
        self.deadline = deadline
        self.declaration = declaration
Beispiel #10
0
def _attach_resource_users(resource: simpy.Resource,
                           callbacks: ProbeCallbacks) -> None:
    def make_wrapper(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            old_users = len(resource.users)
            ret = func(*args, **kwargs)
            new_users = len(resource.users)
            if new_users != old_users:
                for callback in callbacks:
                    callback(new_users)
            return ret

        return wrapper

    resource._do_get = make_wrapper(resource._do_get)  # type: ignore
    resource._do_put = make_wrapper(resource._do_put)  # type: ignore
Beispiel #11
0
def _attach_resource_queue(resource: simpy.Resource,
                           callbacks: ProbeCallbacks) -> None:
    def make_wrapper(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            old_queue = len(resource.queue)
            ret = func(*args, **kwargs)
            new_queue = len(resource.queue)
            if new_queue != old_queue:
                for callback in callbacks:
                    callback(new_queue)
            return ret

        return wrapper

    resource.request = make_wrapper(resource.request)  # type: ignore
    resource._trigger_put = make_wrapper(resource._trigger_put)  # type: ignore
Beispiel #12
0
 def __init__(self, network, S, speed, outbuf_cap, environment):
     super(Server, self).__init__()
     self.quality_levels = [1.5*S, 4.0*S, 7.5*S, 12*S, 68*S]
     self.network = network
     self.S = S
     self.outbuf_cap = outbuf_cap
     self.outbuf_size = 0
     self.env = environment
     self.speed = speed  # Mbps
     self.network_interface = Resource(self.env, 1)
     self.buf_sz = []
     self.time = []
     self.nclientsN = 0
     self.nclients = []
     self.time_clients = []
     self.sender = None
     self.data = None
Beispiel #13
0
    def __init__(self, id=None, name=None, **kw):
        Entity.__init__(self, id=id, name=name)

        self.Res = Resource(self.capacity)
        # dimension data
        self.width = 2.0
        self.height = 2.0
        self.lenght = 2.0
Beispiel #14
0
def process(kwargs: SystemArgs):
    event_store = kwargs['EVENT_STORE']
    env = kwargs['ENV']
    kitchen_layout = kwargs['WORLD'].component_for_entity(1, KitchenLayout)
    # Creates a resource to manage cooks concurrently
    kitchen_layout.available_cooks = Resource(env, kitchen_layout.personnel)
    # For areas that have a max_capacity, create a resource to manage it
    for k, v in kitchen_layout.areas.items():
        if v.max_resources > 0:
            v.resource = Resource(env, v.max_resources)
    # Sink area needs an extra info - amount of dishes piling up
    kitchen_layout.areas['Sink'].dishes = 0
    handlers = {
        IncomingOrderEventTag: handle_incoming_order,
        CompleteOrderEventTag: handle_complete_order
    }
    while True:
        event = yield event_store.get(filter_function)
        handlers[event.type](event.payload, kwargs)
def resource_run(env):
    begin_t = time.time()
    car_arrive_gap = 0
    bcs = Resource(env, capacity=2)
    for i in range(6):
        car_arrive_time = car_arrive_gap * i
        env.process(car_req(env, 'Car %d' % i, bcs, car_arrive_time, 5))
    env.run()
    run_t = time.time() - begin_t
    print(run_t)
Beispiel #16
0
    def __init__(self, env, duration, staff=float('inf'), budget=float('inf')):
        """Initiate financial recovery program attributes.

        Keyword Arguments:
        env -- simpy.Envionment() object
        duration -- io.ProbabilityDistribution() object
        staff -- Integer, indicating number of staff assigned to the programs
        budget -- Integer or float, indicating the initial budget available from
                    the recovery program.

        Attribute Changes:
        self.staff -- A simpy.Resource() object with a capacity == staff arg
        self.budget -- A simpy.Container() object with a initial value == budget arg
        self.duration -- A function that is used to calculate random durations
                            for the program process
        """
        self.env = env
        self.staff = Resource(self.env, capacity=staff)
        self.budget = Container(self.env, init=budget)
        self.duration = duration
Beispiel #17
0
def car(env,name,bcs:simpy.Resource,driving_time,charge_duration):
    # simulate driving to the BCS
    yield env.timeout(driving_time)
    print('%s arriving at %d' % (name, env.now))

    #Request one of its charging spots
    with bcs.request() as req:
        yield req

        # charge the battery
        print('%s starting to charge at %s' % (name, env.now))
        yield env.timeout(charge_duration)
        print('%s leaving the bcs at %s' % (name, env.now))
Beispiel #18
0
def main_run():
    """"""
    env = Environment()
    priority_store = PriorityStore(env=env)
    res_port = Resource(env=env, capacity=2)
    for i in range(NUM_PACKAGE):
        env.process(
            put_package_queue(env=env,
                              id=i,
                              res=res_port,
                              queue=priority_store))
    #env.process(get_package(env, priority_store))
    env.run()
Beispiel #19
0
 def __init__(self, env, cp_params):
     self.env = env
     self.in_pipe = Store(self.env) # TODO: define capacity in cp_params
     self.pending_jobs = {}
     self.response_times = []
     self.interarrivals = []
     self.queue_times = []
     self.num_cores = cp_params['num_cores']
     self.used_cores = 0
     self.core_speed = random_number(cp_params['core_speed'])
     self.cores = Resource(self.num_cores)
     self.name = cp_params['name']
     self.jobs_completed = 0
     self.sim_components = None
     self.data_res = []
     self.idle_time = 0
     self.time_last_arrival = None
Beispiel #20
0
 def __init__(self, address: str,
              radio: Callable[[str], Generator[Event, Any, Any]],
              env: Environment) -> None:
     self.address = address
     self._radio = radio
     self.env = env
     # noinspection PyArgumentEqualDefault
     # 'capacity' sets the quantity of packets that can be sent at the same time
     # 'capacity=1' sets a more realistic model with queue delay for congested networks
     # 'capacity=9999999' sets a less realistic model without queue delay for congested networks
     self._output_queue = Resource(env, capacity=1)
     # List to save messages in format: (timestamp, message)
     # Used to calculate performance
     self._received_messages = []
     self._output_queue_messages = []
     self._message_sending = []
     self._message_sent = []
Beispiel #21
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.cashier = Cashier(self)

        self.customer_queue = Resource(self.env)
        self.auto_probe('customer_queue', trace_queue=True, vcd={'init': 0})

        feed_capacity = self.env.config['checkout.feed_capacity']
        self.feed_belt = Queue(self.env, capacity=feed_capacity)
        self.auto_probe('feed_belt', vcd={})

        bag_area_capacity = self.env.config['checkout.bag_area_capacity']
        self.bag_area = Queue(self.env, capacity=bag_area_capacity)
        self.auto_probe('bag_area', vcd={})

        self.baggers = Container(self.env)
        self.auto_probe('baggers', vcd={})
Beispiel #22
0
def cross_sim():
    """
    cross module test: Cross 模块测试单元
    """
    env = Environment()
    INPUT_QUEUE_DIC.update({
        'x1_in1': PriorityStore(env=env),
        'x1_in2': PriorityStore(env=env)
    })
    generator_queue_res = Resource(env=env, capacity=NUM_PORT_ABLE)
    env.process(
        machine_package(env=env, generator_queue_res=generator_queue_res))
    OUTPUT_QUEUE = PriorityStore(env)
    Cross(env=env,
          id_x=CROSS_ID,
          input_dic=INPUT_QUEUE_DIC,
          out_put=OUTPUT_QUEUE)
    env.run(until=50)
Beispiel #23
0
class Server(object):
    """Documentation for Server

    """
    def __init__(self, network, S, speed, outbuf_cap, environment):
        super(Server, self).__init__()
        self.quality_levels = [1.5*S, 4.0*S, 7.5*S, 12*S, 68*S]
        self.network = network
        self.S = S
        self.outbuf_cap = outbuf_cap
        self.outbuf_size = 0
        self.env = environment
        self.speed = speed  # Mbps
        self.network_interface = Resource(self.env, 1)
        self.buf_sz = []
        self.time = []
        self.nclientsN = 0
        self.nclients = []
        self.time_clients = []
        self.sender = None
        self.data = None

    def incoming_packet(self, sender, data):
        #print("packet received from client: ", self.incoming_data)
        self.sender = sender
        self.data = data
        quality = self.data.content
        timestamp = self.data.timestamp
        if self.outbuf_size + self.quality_levels[quality] > self.outbuf_cap:
            yield self.env.process(self.network.send(self, self.sender,
                                                     Data(0, "ERROR", timestamp)))
        else:
            yield self.env.process(self.process(self.sender, quality, timestamp))

    def process(self, sender, quality, timestamp):
        self.outbuf_size += self.quality_levels[quality]
        self.buf_sz.append(self.outbuf_size)
        self.time.append(self.env.now)
        with self.network_interface.request() as req:
            yield req
            yield self.env.process(self.network.send(self, sender,
                                    Data(self.quality_levels[quality], "", timestamp, quality)))
        self.outbuf_size -= self.quality_levels[quality]
Beispiel #24
0
    def __init__(self, env, id, area, perimeter, can_see, replenish_rate=0.1):
        """

        :param env:
        :type env: Environment
        :type id: int
        :param area:
        :type area: float
        :param perimeter:
        :type perimeter: float
        :param can_see:
        :type can_see: dict[int, float]
        """
        r_cap = int(area / 0.17384) + 1
        # r_cap = MAX_CAPACITY
        perimeter = int(perimeter * DEG_TO_KM) + 1

        self.env = env
        self.id = id
        self.area = area
        self.perimeter = perimeter
        self._can_see = can_see
        self.can_see, self.probs = self.normalise(can_see)
        self.replenish_rate = replenish_rate
        self.r = Resource(self.env, capacity=r_cap)
        self.c = Container(self.env, capacity=perimeter, init=perimeter)
        self.action = self.env.process(self.replenish())
        self._populations = set()

        self._pop = None
        self._pop_calc_time = None

        self._density = None
        self._density_calc_time = None

        self._capacity = None
        self._capacity_calc_time = None
def car(env: simpy.Environment, name: str, gas_station: simpy.Resource,
        fuel_pump: simpy.Container) -> Generator:
    """A car arrives at the gas station for refueling.

    It requests one of the gas station's fuel pumps and tries to get the
    desired amount of gas from it. If the stations reservoir is
    depleted, the car has to wait for the tank truck to arrive.

    """
    fuel_tank_level = random.randint(*FUEL_TANK_LEVEL)
    print(f"{name} arriving at gas station at {env.now:.1f}")
    with gas_station.request() as req:
        start = env.now
        # Request one of the gas pumps
        yield req

        # Get the required amount of fuel
        liters_required = FUEL_TANK_SIZE - fuel_tank_level
        yield fuel_pump.get(liters_required)

        # The "actual" refueling process takes some time
        yield env.timeout(liters_required / REFUELING_SPEED)

        print(f"{name} finished refueling in {env.now - start:.1f} seconds")
Beispiel #26
0
            or (parameters["Time at work [min]"] > 15.0 * 60)
            or (parameters["Battery capacity [kwh]"] < 5.0)
            or (parameters["Battery capacity [kwh]"] > 100.0)
            or ((2 * parameters["Distance to workplace [km]"]) >
                parameters["Range [km]"])):
        return (False)
    return (True)


n_cars = 30000
env = simpy.Environment()

n_stations = 200
globalEnergyGiant = EnergyProvider()
# Charging stations
publicChargingStation = Resource(env, capacity=n_stations)

cars = []
i = 0

while i < n_cars:
    bat_ctrl = BatteryController(env, globalEnergyGiant)
    car = REVCar(env, bat_ctrl)

    if sane(car):
        cars.append(car)
        i += 1

stats = describe(cars)

env.run(60 * 24 - 1)
"""
 simpy tutorial process interaction part
"""
from simpy import Environment, Resource


def car(env, name, bcs, driving_time, charge_duration):
    "battery charging station (BCS) is bsc resource "
    yield env.timeout(driving_time)
    print("{name} arrive at battery charging station at {time}".format(
        name=name, time=env.now))
    with bcs.request() as req:
        yield req
        print('%s starting to charge at %s' % (name, env.now))
        yield env.timeout(charge_duration)
        print('%s leaving the bcs at %s' % (name, env.now))


if __name__ == '__main__':
    env = Environment()
    bcs = Resource(env, capacity=2)
    for i in range(4):
        env.process(car(env, 'Car {num}'.format(num=str(i)), bcs, i * 2, 5))
    env.run()
Beispiel #28
0
class GasStation(Component):
    """A gas station has a fuel reservoir shared among several fuel pumps.

    The gas station has a traffic generator process that causes cars to arrive
    to fill up their tanks.

    As the cars fill up, the reservoir's level goes down. When the level goes
    below a critical threshold, the gas station makes a request to the tanker
    company for a tanker truck to refill the reservoir.

    """
    base_name = 'station'

    def __init__(self, *args, **kwargs):
        super(GasStation, self).__init__(*args, **kwargs)
        config = self.env.config
        self.add_connections('tanker_company')
        self.arrival_interval = config.get('gas_station.arrival_interval', 60)

        station_capacity = config.get('gas_station.capacity', 200)
        self.reservoir = Container(self.env,
                                   capacity=station_capacity,
                                   init=station_capacity)
        self.auto_probe('reservoir', log={})

        self.threshold_pct = config.get('gas_station.threshold_pct', 10)

        self.pump_rate = config.get('gas_station.pump_rate', 2)
        num_pumps = config.get('gas_station.pumps', 2)
        self.fuel_pumps = Resource(self.env, capacity=num_pumps)
        self.auto_probe('fuel_pumps', log={})

        self.car_capacity = config.get('car.capacity', 50)
        self.car_level_range = config.get('car.level', [5, 25])

        # A gas station has two persistent processes. One to monitor the
        # reservoir level and one that models the arrival of cars at the
        # station. Desmod starts these processes before simulation phase.
        self.add_processes(self._monitor_reservoir, self._traffic_generator)

    @property
    def reservoir_pct(self):
        return self.reservoir.level / self.reservoir.capacity * 100

    def _monitor_reservoir(self):
        """Periodically monitor reservoir level.

        The a request is made to the tanker company when the reservoir falls
        below a critical threshold.

        """
        while True:
            yield self.env.timeout(10)
            if self.reservoir_pct < self.threshold_pct:
                done_event = self.env.event()
                yield self.tanker_company.request_truck(self, done_event)
                yield done_event

    def _traffic_generator(self):
        """Model the sporadic arrival of cars to the gas station."""
        for i in count():
            interval = self.env.rand.expovariate(1 / self.arrival_interval)
            yield self.env.timeout(interval)
            self.env.process(self._car(i))

    def _car(self, i):
        """Model a car transacting fuel."""
        with self.fuel_pumps.request() as pump_req:
            self.info('car{} awaiting pump'.format(i))
            yield pump_req
            self.info('car{} at pump'.format(i))
            car_level = self.env.rand.randint(*self.car_level_range)
            amount = self.car_capacity - car_level
            t0 = self.env.now
            for _ in range(amount):
                yield self.reservoir.get(1)
                yield self.env.timeout(1 / self.pump_rate)
            pump_time = self.env.now - t0
            self.info('car{} pumped {}L in {:.0f}s'.format(
                i, amount, pump_time))
Beispiel #29
0
        #  每次服务队列迭代server queue 获取在一次
        yield req
        print(name, 'uer obj is--->', res.users[0], 'at', env.now)
        #  capacity个request都延迟1秒才能释放资源,
        #  with内的yield timeout 用于阻塞正在服务的request一段时间才释放,
        #  释放后被阻塞的waiting request 立即获得服务资源
        yield env.timeout(5)
        print(name, 'out with', env.now)
    #  with外的yield timeout不会阻塞waiting request获得服务资源,
    #
    yield env.timeout(2)
    print(name, 'out process at',env.now)


def multi_process(env, res):
    num = 0
    while True:
        # yield env.timeout(1)
        env.process(user(env, res, num))
        num += 1
        if num >= 10:
            break


if __name__  == '__main__':
    env = Environment()
    res = Resource(env, capacity=5)
    #  env.process(multi_process(env, res))
    multi_process(env, res)
    env.run(until=15)
Beispiel #30
0
class Block:
    """
    Provides simulation-specific behavior of a basic block.
    Entities are accepted via the process_entity entry-point, and standard processing steps are executed.
    Actual processing behavior is to be provided by subclasses, implementing the actual_processing method.
    """

    def __init__(self, env: Environment, name: str, block_capacity=float("inf")):
        self.name = name
        self.env: Environment = env
        self.overall_count_in = 0
        on_enter_or_exit_method_callable = Callable[
            [Entity, Optional[Block], Optional[Block]], None
        ]
        self.do_on_enter_list: List[on_enter_or_exit_method_callable] = []
        self.do_on_exit_list: List[on_enter_or_exit_method_callable] = []
        self.entities: List[Entity] = []
        self.successors: List[Block] = []
        self.block_resource = Resource(env=env, capacity=block_capacity)
        self.state_manager = StateManager(self.on_block_state_change)

        self.env.process(self.late_state_evaluation())

    def on_enter(self, entity: Entity):
        """called when process_entity starts"""
        for method in self.do_on_enter_list:
            method(entity, None, self)

    def on_exit(self: "Block", entity: Entity, successor: "Block"):
        """called when an entities leaves the block"""
        self.entities.remove(entity)
        for method in self.do_on_exit_list:
            method(entity, self, successor)
        self.on_block_change()
        self.on_entity_movement(entity, successor)

    def process_entity(self, entity: Entity):
        """main entry point for entities coming from predecessors"""
        entity.time_of_last_arrival = self.env.now
        self.on_enter(entity)
        self.overall_count_in += 1
        yield self.env.process(self._process_entity(entity))

    def _process_entity(self, entity: Entity):
        """internal entry point for start of entity processing without calling on_enter or setting entity.time_of_last_arrival.
        useful e.g. for wip init"""
        self.entities.append(entity)
        self.on_block_change()

        # processing
        self.state_manager.increment_state_count(States.busy)
        entity.current_process = self.env.process(self.actual_processing(entity))
        yield entity.current_process  # might be used for interrupt

        # wait for successor
        successor = self.find_successor(entity)
        req = successor.block_resource.request()
        self.state_manager.increment_state_count(States.blocked)
        self.state_manager.decrement_state_count(States.busy)
        yield req  # wait until the chosen successor is ready

        # leaving
        self.block_resource.release(entity.block_resource_request)
        entity.block_resource_request = req  # remember to be released

        self.on_exit(entity, successor)
        self.state_manager.decrement_state_count(States.blocked)

        self.env.process(successor.process_entity(entity))

    def find_successor(self, entity: Entity):
        """find next block to send entity to"""
        return self.successors[0]

    def on_block_change(self):
        """called on block change"""

    def on_block_state_change(self, state, new_value):
        """called when state of the block changes"""

    def on_entity_movement(self, entity: Entity, successor: "Block"):
        """called on entity movement from this block to the successor"""

    def late_state_evaluation(self):
        """schedule evaluation on sim start,
        when the visualizer has been loaded"""
        yield self.env.timeout(0)
        self.state_manager.evaluate_state_count()

    def actual_processing(self, entity: Entity):
        """to be implemented by concrete subclasses"""
        raise NotImplementedError()
Beispiel #31
0
 def _resource_hospital(self, packages):
     """"""
     people_res = Resource(self.env, self.hospital_capacity)
     with people_res.request() as req:
         yield req
         self.env.process(self._put_packages_into_out_queue(packages))
Beispiel #32
0
class GasStation(Component):
    """A gas station has a fuel reservoir shared among several fuel pumps.

    The gas station has a traffic generator process that causes cars to arrive
    to fill up their tanks.

    As the cars fill up, the reservoir's level goes down. When the level goes
    below a critical threshold, the gas station makes a request to the tanker
    company for a tanker truck to refill the reservoir.

    """
    base_name = 'station'

    def __init__(self, *args, **kwargs):
        super(GasStation, self).__init__(*args, **kwargs)
        config = self.env.config
        self.add_connections('tanker_company')
        self.arrival_interval = config.get('gas_station.arrival_interval', 60)

        station_capacity = config.get('gas_station.capacity', 200)
        self.reservoir = Container(self.env,
                                   capacity=station_capacity,
                                   init=station_capacity)
        self.auto_probe('reservoir', log={})

        self.threshold_pct = config.get('gas_station.threshold_pct', 10)

        self.pump_rate = config.get('gas_station.pump_rate', 2)
        num_pumps = config.get('gas_station.pumps', 2)
        self.fuel_pumps = Resource(self.env, capacity=num_pumps)
        self.auto_probe('fuel_pumps', log={})

        self.car_capacity = config.get('car.capacity', 50)
        self.car_level_range = config.get('car.level', [5, 25])

        # A gas station has two persistent processes. One to monitor the
        # reservoir level and one that models the arrival of cars at the
        # station. Desmod starts these processes before simulation phase.
        self.add_processes(self._monitor_reservoir, self._traffic_generator)

    @property
    def reservoir_pct(self):
        return self.reservoir.level / self.reservoir.capacity * 100

    def _monitor_reservoir(self):
        """Periodically monitor reservoir level.

        The a request is made to the tanker company when the reservoir falls
        below a critical threshold.

        """
        while True:
            yield self.env.timeout(10)
            if self.reservoir_pct < self.threshold_pct:
                done_event = self.env.event()
                yield self.tanker_company.request_truck(self, done_event)
                yield done_event

    def _traffic_generator(self):
        """Model the sporadic arrival of cars to the gas station."""
        for i in count():
            interval = self.env.rand.expovariate(1 / self.arrival_interval)
            yield self.env.timeout(interval)
            self.env.process(self._car(i))

    def _car(self, i):
        """Model a car transacting fuel."""
        with self.fuel_pumps.request() as pump_req:
            self.info('car{} awaiting pump'.format(i))
            yield pump_req
            self.info('car{} at pump'.format(i))
            car_level = self.env.rand.randint(*self.car_level_range)
            amount = self.car_capacity - car_level
            t0 = self.env.now
            for _ in range(amount):
                yield self.reservoir.get(1)
                yield self.env.timeout(1 / self.pump_rate)
            pump_time = self.env.now - t0
            self.info('car{} pumped {}L in {:.0f}s'.format(
                i, amount, pump_time))