# Resource¶

Resources are a powerful way of process interaction.

A resource has always a capacity (which can be zero and even negative). This capacity will be specified at time of creation, but may change over time. There are two of types resources:

• standard resources, where each claim is associated with a component (the claimer). It is not necessary that the claimed quantities are integer.
• anonymous resources, where only the claimed quantity is registered. This is most useful for dealing with levels, lengths, etc.

Resources are defined like

clerks = Resource('clerks', capacity=3)


And then a component can request a clerk

yield self.request(clerks)  # request 1 from clerks


It is also possible to request for more resources at once

yield self.request(clerks,(assistance,2))  # request 1 from clerks AND 2 from assistance


AResources have a queue requesters containing all components trying to claim from the resource. And a queue claimers containing all components claiming from the resource (not for anonymous resources).

It is possible to release a quantity from a resource with c.release(), e.g.

self.release(r)  # releases all claimed quantity from r
self.release((r,2))  # release quantity 2 from r


Alternatively, it is possible to release from a resource directly, e.g.

r.release()  # releases the total quantity from all claiming components
r.release(10)  # releases 10 from the resource; only valid for anonymous resources


After a release, all requesting components will be checked whether their claim can be honored.

Resources have a number monitors:

• claimers().length
• claimers().length_of_stay
• requesters().length
• requesters().length_of_stay
• claimed_quantity
• available_quantity
• capacity
• occupancy (=claimed_quantity / capacity)

By default, all monitors are enabled.

With r.print_statistics() the key statistics of these all monitors are printed.

E.g.:

Statistics of clerk at     50000.000
all    excl.zero         zero
-------------------------------------------- -------------- ------------ ------------ ------------
Length of requesters of clerk                duration          50000        48499.381     1500.619
mean                  8.427        8.687
std.deviation         4.852        4.691

minimum               0            1
median                9           10
90% percentile       14           14
95% percentile       16           16
maximum              21           21

Length of stay in requesters of clerk        entries            4995         4933           62
mean                 84.345       85.405
std.deviation        48.309       47.672

minimum               0            0.006
median               94.843       95.411
90% percentile      142.751      142.975
95% percentile      157.467      157.611
maximum             202.153      202.153

Length of claimers of clerk                  duration          50000        50000            0
mean                  2.996        2.996
std.deviation         0.068        0.068

minimum               1            1
median                3            3
90% percentile        3            3
95% percentile        3            3
maximum               3            3

Length of stay in claimers of clerk          entries            4992         4992            0
mean                 30           30
std.deviation         0.000        0.000

minimum              30.000       30.000
median               30           30
90% percentile       30           30
95% percentile       30           30
maximum              30.000       30.000

Capacity of clerk                            duration          50000        50000            0
mean                  3            3
std.deviation         0            0

minimum               3            3
median                3            3
90% percentile        3            3
95% percentile        3            3
maximum               3            3

Available quantity of clerk                  duration          50000          187.145    49812.855
mean                  0.004        1.078
std.deviation         0.068        0.268

minimum               0            1
median                0            1
90% percentile        0            1
95% percentile        0            2
maximum               2            2

Claimed quantity of clerk                    duration          50000        50000            0
mean                  2.996        2.996
std.deviation         0.068        0.068

minimum               1            1
median                3            3
90% percentile        3            3
95% percentile        3            3
maximum               3            3

Occupancy of clerks                          duration          50000        50000            0
mean                  0.999        0.999
std.deviation         0.023        0.023

minimum               0.333        0.333
median                1            1
90% percentile        1            1
95% percentile        1            1
maximum               1            1


With r.print_info() a summary of the contents of the queues can be printed.

E.g.

Resource 0x112e8f0b8
name=clerk
capacity=3
requesting component(s):
customer.4995        quantity=1
customer.4996        quantity=1
claimed_quantity=3
claimed by:
customer.4992        quantity=1
customer.4993        quantity=1
customer.4994        quantity=1


The capacity may be changed with r.set_capacity(x). Note that this may lead to requesting components to be honored.

Querying of the capacity, claimed quantity, available quantity and occupancy can be done via the label monitors: r.capacity(), r.claimed_quantity(), r.available_quantity() and r.occupancy()

If the capacity of a resource is constant, which is very common, the mean occupancy can be found with

r.occupancy.mean()


When the capacity changes over time, it is recommended to use

occupancy = r.claimed_quantity.mean() / r.capacity.mean()


to obtain the mean occupancy.

Note that the occupancy is set to 0 if the capacity of the resource is <= 0.

## Additional methods for anonymous resources¶

For anonymous resources, it may be not allowed to exceed the capacity and have a component wait for enough (claimed) capacity to be available. That may be accomplished by using a negative quantity in the self.request call.

Alternatively, it possible to use the Component.put method, where quantities of anonymous resources are negated. For symmetry reasons, salabim also offers the Component.get() method, which is behaves exactly like Component.request.

The model below illustrates the use of get and put.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 # Gas station.py import salabim as sim # based on SimPy example model GAS_STATION_SIZE = 200.0 # liters THRESHOLD = 25.0 # Threshold for calling the tank truck (in %) FUEL_TANK_SIZE = 50.0 # liters # Min/max levels of fuel tanks (in liters) FUEL_TANK_LEVEL = sim.Uniform(5, 25) REFUELING_SPEED = 2.0 # liters / second TANK_TRUCK_TIME = 300.0 # Seconds it takes the tank truck to arrive T_INTER = sim.Uniform(10, 100) # Create a car every [min, max] seconds SIM_TIME = 200000 # Simulation time in seconds class Car(sim.Component): """ 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. """ def process(self): fuel_tank_level = int(FUEL_TANK_LEVEL.sample()) yield self.request(gas_station) liters_required = FUEL_TANK_SIZE - fuel_tank_level if (fuel_pump.available_quantity() - liters_required) / fuel_pump.capacity() * 100 < THRESHOLD: TankTruck() yield self.get((fuel_pump, liters_required)) yield self.hold(liters_required / REFUELING_SPEED) class TankTruck(sim.Component): def process(self): yield self.hold(TANK_TRUCK_TIME) amount = fuel_pump.claimed_quantity() yield self.put((fuel_pump, amount)) class CarGenerator(sim.Component): """ Generate new cars that arrive at the gas station. """ def process(self): while True: yield self.hold(T_INTER.sample()) Car() # Setup and start the simulation env = sim.Environment(trace=False) print("Gas Station refuelling") # Create environment and start processes gas_station = sim.Resource("gas_station", 2) fuel_pump = sim.Resource("fuel_pump", capacity=GAS_STATION_SIZE, anonymous=True) tank_truck = TankTruck() CarGenerator() env.run(SIM_TIME) fuel_pump.capacity.print_histogram() fuel_pump.claimed_quantity.print_histogram() fuel_pump.available_quantity.print_histogram() gas_station.requesters().length.print_histogram() gas_station.requesters().length_of_stay.print_histogram(30, 0, 10)