The solution is to sublcass StoreGet and base.BaseResource. Here is a minimal example:
from simpy.core import BoundClass
from simpy.resources import base
from simpy.resources.store import StorePut, StoreGet
from functools import reduce
class MultipleItemStoreGet(StoreGet):
""" Store a list of items you want to get
"""
def __init__(self, store, item_filters):
self.item_filters= item_filters if isinstance(item_filters, list) else [item_filters]
super(StoreGet, self).__init__(store)
class MultipleItemStore(base.BaseResource):
def __init__(self, env=None):
super(MultipleItemStore, self).__init__(env=set_env(env), capacity=inf)
self.items = []
put = BoundClass(StorePut)
"""Request to put *item* into the store."""
get = BoundClass(MultipleItemStoreGet)
"""Request to get an *item* out of the store."""
def _do_put(self, event):
# here you could add code for multiple items being put back at once
# for now, just assume one item at a time
self.items.append(event.item)
event.succeed()
def _do_get(self, event):
matches = []
items_needed = len(event.item_filters)
for filter in event.item_filters:
matches.append([x for x in self.items if filter(x)])
# if no match was found, exit
return True
unique_matches = reduce(lambda a, b: a.union(b), matches, set())
if len(unique_matches) < items_needed:
# not enough unique matches
return True
# You'll need to do more checking to make sure the unique matches can still fit all the requirements
# ...
# return the items
event.succeed(unique_matches[:items_needed ])
return True
This code is very rough and untested. It should give you a starting point for implementing multiple item getting.
Cheers,
James