Initial commit
This commit is contained in:
275
skills/simpy/references/resources.md
Normal file
275
skills/simpy/references/resources.md
Normal file
@@ -0,0 +1,275 @@
|
||||
# SimPy Shared Resources
|
||||
|
||||
This guide covers all resource types in SimPy for modeling congestion points and resource allocation.
|
||||
|
||||
## Resource Types Overview
|
||||
|
||||
SimPy provides three main categories of shared resources:
|
||||
|
||||
1. **Resources** - Limited capacity resources (e.g., gas pumps, servers)
|
||||
2. **Containers** - Homogeneous bulk materials (e.g., fuel tanks, silos)
|
||||
3. **Stores** - Python object storage (e.g., item queues, warehouses)
|
||||
|
||||
## 1. Resources
|
||||
|
||||
Model resources that can be used by a limited number of processes at a time.
|
||||
|
||||
### Resource (Basic)
|
||||
|
||||
The basic resource is a semaphore with specified capacity.
|
||||
|
||||
```python
|
||||
import simpy
|
||||
|
||||
env = simpy.Environment()
|
||||
resource = simpy.Resource(env, capacity=2)
|
||||
|
||||
def process(env, resource, name):
|
||||
with resource.request() as req:
|
||||
yield req
|
||||
print(f'{name} has the resource at {env.now}')
|
||||
yield env.timeout(5)
|
||||
print(f'{name} releases the resource at {env.now}')
|
||||
|
||||
env.process(process(env, resource, 'Process 1'))
|
||||
env.process(process(env, resource, 'Process 2'))
|
||||
env.process(process(env, resource, 'Process 3'))
|
||||
env.run()
|
||||
```
|
||||
|
||||
**Key properties:**
|
||||
- `capacity` - Maximum number of concurrent users (default: 1)
|
||||
- `count` - Current number of users
|
||||
- `queue` - List of queued requests
|
||||
|
||||
### PriorityResource
|
||||
|
||||
Extends basic resource with priority levels (lower numbers = higher priority).
|
||||
|
||||
```python
|
||||
import simpy
|
||||
|
||||
env = simpy.Environment()
|
||||
resource = simpy.PriorityResource(env, capacity=1)
|
||||
|
||||
def process(env, resource, name, priority):
|
||||
with resource.request(priority=priority) as req:
|
||||
yield req
|
||||
print(f'{name} (priority {priority}) has the resource at {env.now}')
|
||||
yield env.timeout(5)
|
||||
|
||||
env.process(process(env, resource, 'Low priority', priority=10))
|
||||
env.process(process(env, resource, 'High priority', priority=1))
|
||||
env.run()
|
||||
```
|
||||
|
||||
**Use cases:**
|
||||
- Emergency services (ambulances before regular vehicles)
|
||||
- VIP customer queues
|
||||
- Job scheduling with priorities
|
||||
|
||||
### PreemptiveResource
|
||||
|
||||
Allows high-priority requests to interrupt lower-priority users.
|
||||
|
||||
```python
|
||||
import simpy
|
||||
|
||||
env = simpy.Environment()
|
||||
resource = simpy.PreemptiveResource(env, capacity=1)
|
||||
|
||||
def process(env, resource, name, priority):
|
||||
with resource.request(priority=priority) as req:
|
||||
try:
|
||||
yield req
|
||||
print(f'{name} acquired resource at {env.now}')
|
||||
yield env.timeout(10)
|
||||
print(f'{name} finished at {env.now}')
|
||||
except simpy.Interrupt:
|
||||
print(f'{name} was preempted at {env.now}')
|
||||
|
||||
env.process(process(env, resource, 'Low priority', priority=10))
|
||||
env.process(process(env, resource, 'High priority', priority=1))
|
||||
env.run()
|
||||
```
|
||||
|
||||
**Use cases:**
|
||||
- Operating system CPU scheduling
|
||||
- Emergency room triage
|
||||
- Network packet prioritization
|
||||
|
||||
## 2. Containers
|
||||
|
||||
Model production and consumption of homogeneous bulk materials (continuous or discrete).
|
||||
|
||||
```python
|
||||
import simpy
|
||||
|
||||
env = simpy.Environment()
|
||||
container = simpy.Container(env, capacity=100, init=50)
|
||||
|
||||
def producer(env, container):
|
||||
while True:
|
||||
yield env.timeout(5)
|
||||
yield container.put(20)
|
||||
print(f'Produced 20. Level: {container.level}')
|
||||
|
||||
def consumer(env, container):
|
||||
while True:
|
||||
yield env.timeout(7)
|
||||
yield container.get(15)
|
||||
print(f'Consumed 15. Level: {container.level}')
|
||||
|
||||
env.process(producer(env, container))
|
||||
env.process(consumer(env, container))
|
||||
env.run(until=50)
|
||||
```
|
||||
|
||||
**Key properties:**
|
||||
- `capacity` - Maximum amount (default: float('inf'))
|
||||
- `level` - Current amount
|
||||
- `init` - Initial amount (default: 0)
|
||||
|
||||
**Operations:**
|
||||
- `put(amount)` - Add to container (blocks if full)
|
||||
- `get(amount)` - Remove from container (blocks if insufficient)
|
||||
|
||||
**Use cases:**
|
||||
- Gas station fuel tanks
|
||||
- Buffer storage in manufacturing
|
||||
- Water reservoirs
|
||||
- Battery charge levels
|
||||
|
||||
## 3. Stores
|
||||
|
||||
Model production and consumption of Python objects.
|
||||
|
||||
### Store (Basic)
|
||||
|
||||
Generic FIFO object storage.
|
||||
|
||||
```python
|
||||
import simpy
|
||||
|
||||
env = simpy.Environment()
|
||||
store = simpy.Store(env, capacity=2)
|
||||
|
||||
def producer(env, store):
|
||||
for i in range(5):
|
||||
yield env.timeout(2)
|
||||
item = f'Item {i}'
|
||||
yield store.put(item)
|
||||
print(f'Produced {item} at {env.now}')
|
||||
|
||||
def consumer(env, store):
|
||||
while True:
|
||||
yield env.timeout(3)
|
||||
item = yield store.get()
|
||||
print(f'Consumed {item} at {env.now}')
|
||||
|
||||
env.process(producer(env, store))
|
||||
env.process(consumer(env, store))
|
||||
env.run()
|
||||
```
|
||||
|
||||
**Key properties:**
|
||||
- `capacity` - Maximum number of items (default: float('inf'))
|
||||
- `items` - List of stored items
|
||||
|
||||
**Operations:**
|
||||
- `put(item)` - Add item to store (blocks if full)
|
||||
- `get()` - Remove and return item (blocks if empty)
|
||||
|
||||
### FilterStore
|
||||
|
||||
Allows retrieval of specific objects based on filter functions.
|
||||
|
||||
```python
|
||||
import simpy
|
||||
|
||||
env = simpy.Environment()
|
||||
store = simpy.FilterStore(env, capacity=10)
|
||||
|
||||
def producer(env, store):
|
||||
for color in ['red', 'blue', 'green', 'red', 'blue']:
|
||||
yield env.timeout(1)
|
||||
yield store.put({'color': color, 'time': env.now})
|
||||
print(f'Produced {color} item at {env.now}')
|
||||
|
||||
def consumer(env, store, color):
|
||||
while True:
|
||||
yield env.timeout(2)
|
||||
item = yield store.get(lambda x: x['color'] == color)
|
||||
print(f'{color} consumer got item from {item["time"]} at {env.now}')
|
||||
|
||||
env.process(producer(env, store))
|
||||
env.process(consumer(env, store, 'red'))
|
||||
env.process(consumer(env, store, 'blue'))
|
||||
env.run(until=15)
|
||||
```
|
||||
|
||||
**Use cases:**
|
||||
- Warehouse item picking (specific SKUs)
|
||||
- Job queues with skill matching
|
||||
- Packet routing by destination
|
||||
|
||||
### PriorityStore
|
||||
|
||||
Items retrieved in priority order (lowest first).
|
||||
|
||||
```python
|
||||
import simpy
|
||||
|
||||
class PriorityItem:
|
||||
def __init__(self, priority, data):
|
||||
self.priority = priority
|
||||
self.data = data
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.priority < other.priority
|
||||
|
||||
env = simpy.Environment()
|
||||
store = simpy.PriorityStore(env, capacity=10)
|
||||
|
||||
def producer(env, store):
|
||||
items = [(10, 'Low'), (1, 'High'), (5, 'Medium')]
|
||||
for priority, name in items:
|
||||
yield env.timeout(1)
|
||||
yield store.put(PriorityItem(priority, name))
|
||||
print(f'Produced {name} priority item')
|
||||
|
||||
def consumer(env, store):
|
||||
while True:
|
||||
yield env.timeout(5)
|
||||
item = yield store.get()
|
||||
print(f'Retrieved {item.data} priority item')
|
||||
|
||||
env.process(producer(env, store))
|
||||
env.process(consumer(env, store))
|
||||
env.run()
|
||||
```
|
||||
|
||||
**Use cases:**
|
||||
- Task scheduling
|
||||
- Print job queues
|
||||
- Message prioritization
|
||||
|
||||
## Choosing the Right Resource Type
|
||||
|
||||
| Scenario | Resource Type |
|
||||
|----------|---------------|
|
||||
| Limited servers/machines | Resource |
|
||||
| Priority-based queuing | PriorityResource |
|
||||
| Preemptive scheduling | PreemptiveResource |
|
||||
| Fuel, water, bulk materials | Container |
|
||||
| Generic item queue (FIFO) | Store |
|
||||
| Selective item retrieval | FilterStore |
|
||||
| Priority-ordered items | PriorityStore |
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Capacity planning**: Set realistic capacities based on system constraints
|
||||
2. **Request patterns**: Use context managers (`with resource.request()`) for automatic cleanup
|
||||
3. **Error handling**: Wrap preemptive resources in try-except for Interrupt handling
|
||||
4. **Monitoring**: Track queue lengths and utilization (see monitoring.md)
|
||||
5. **Performance**: FilterStore and PriorityStore have O(n) retrieval time; use wisely for large stores
|
||||
Reference in New Issue
Block a user