Store_plot

http://packages.python.org/SimPy/Manuals/Manual.html?highlight=inventory#stores

The Store object sObj is established by a statement like the following:

1 2 3 4 5 6 7 8

sObj = Store(name='a_store',              unitName='units',              capacity='unbounded',              initialBuffered=None,              putQType=FIFO,              getQType=FIFO,              monitored=False,              monitorType=Monitor)

where

The Store object sObj also has the following additional attributes:

Putting objects into a Store

Processes can request items from a Store and the same or other processes can offer items to it. First look at the simpler of these operations, the yield put.

A process, the offerer, which is usually but not necessarily different from the requester, can offer a list of items to sObj by a yield put statement:

Here give is a list of any Python objects. If this statement would lead to an overflow (that is, sObj.nrBuffered + len(give) > sObj.capacity) the putting process is passivated and queued (in sObj.putQ) until there is sufficient room. P is an optional priority value (real or integer).

The ordering of processes in a Store’s putQ and getQ behave like those described for the waitQ under Resources , except that they are not preemptable. Thus, priority values are ignored when the queue type is FIFO. Otherwise higher priority values indicate higher priority, etc.

The items in sObj are stored in the form of a queue called sObj.theBuffer, which is in FIFO order unless the user has arranged to sort them into a particular order (see Storing objects in an order below).

Getting objects from a Store

There are two ways of getting objects from a Store. A process, the requester, can either extract the first n objects from sObj or a list of items chosen by a filter function.

Getting n items is achieved by the following statement:

Here n must be a positive integer and P is an optional priority value (real or integer). If sObj does not currently hold enough objects to satisfy this request (that is, n >sObj.nrBuffered) then the requesting process is passivated and queued (in sObj.getQ). Subject to the priority ordering, it will be reactivated when the request can be satisfied.

The retrieved objects are returned in the list attribute got of the requesting process.

yield get requests with a numerical parameter are honored in priority/FIFO order. Thus, if there are two processes in the Store’s getQ, with the first requesting two items and the second one, the second process gets the requested item only after the first process has been given its two items.

Using the get filter function

The second method is to get a list of items chosen by a filter function, written by the user.

The command, using filter function ffn is as follows:

The user provides a filter function that has a single list argument and returns a list. The argument represents the buffer of the Store. The function must search through the objects in the buffer and return a sub-list of those that satisfy the requirement.

Example The filter function allweight, shown below, is an example of such a filter. The argument, buff, will be automatically replaced in the execution of yieldget,self,store,allweight by the buffer of the Store. In this example the objects in the Store are assumed to have weight attributes. The function allweight selects all those that have a weight attribute over a value W and returns these as a list. The list appears to the calling process as self.got:

1 2 3 4 5 6 7

def allweight(buff):     """filter: get all items with .weight >=W from store"""     result=[]     for i in buff:         if i.weight>=W:             result.append(i)     return result

This might be used as follows:

yield get,self,sObj,allweight [,P]

The retrieved objects are returned in the list attribute got of the requesting process.

Note: ``yield get`` requests with a filter function parameter are not necessarily honored in priority/FIFO order, but rather according to the filter function. An example: There are two processes in the Store’s getQ, with the first requesting an item with a weight attribute less than 2 kilograms and the second one requesting one with a weight attribute less than 3 kilograms. If there is an item in the Store’s buffer with a weight attribute between 2 and 3 and none with an attribute of less than 2, the second get requester gets unblocked before the first one. Effectively, the SimPy run time system runs through all processes in the getQ in sequence and tests their filter functions as long as there are still items in the Store’s buffer.

Example The following program illustrates the use of a Store to model the production and consumption of “widgets”. The widgets are distinguished by their weight:

from SimPy.Simulation import *

from SimPy.SimPlot import *

class ProducerD(Process):

    def __init__(self):

        Process.__init__(self)

    def produce(self):           # the ProducerD PEM

        while True:

            yield put,self,buf,[Widget(9),Widget(7)]

            yield hold,self,10

class ConsumerD(Process):       

    def __init__(self):

        Process.__init__(self)

    def consume(self):           # the ConsumerD PEM

        while True:

            toGet=3

            yield get,self,buf,toGet

            assert len(self.got)==toGet

            print now(),'Get widget weights',\

                 [x.weight for x in self.got]

            yield hold,self,11

class Widget(Lister):

    def __init__(self,weight=0):

        self.weight=weight

widgbuf=[]

for i in range(10):

    widgbuf.append(Widget(5))

initialize()

buf=Store(capacity=11,initialBuffered=widgbuf,monitored=True)

for i in range(3):       # define and activate 3 producer objects

    p=ProducerD()

    activate(p,p.produce())

for i in range(3):       # define and activate 3 consumer objects

    c=ConsumerD()

    activate(c,c.consume())

simulate(until=50)

print 'LenBuffer:',buf.bufferMon     # length of buffer

print 'getQ:',buf.getQMon            # length of getQ

print 'putQ',buf.putQMon             # length of putQ

plt=SimPlot()

#plt.plotStep(buf.getQMon,color='blue')

#plt.plotStep(buf.putQMon,color='blue')

plt.plotStep(buf.bufferMon,color='blue')

plt.mainloop()

===========================================

0 Get widget weights [5, 5, 5]

0 Get widget weights [5, 5, 5]

0 Get widget weights [5, 5, 5]

11 Get widget weights [5, 9, 7]

11 Get widget weights [9, 7, 9]

11 Get widget weights [7, 9, 7]

22 Get widget weights [9, 7, 9]

22 Get widget weights [7, 9, 7]

22 Get widget weights [9, 7, 9]

33 Get widget weights [7, 9, 7]

33 Get widget weights [9, 7, 9]

40 Get widget weights [7, 9, 7]

44 Get widget weights [9, 7, 9]

50 Get widget weights [7, 9, 7]

LenBuffer: [[0, 10], [0, 7], [0, 9], [0, 11], [0, 8], [0, 10], [0, 7], [10, 9], [10, 11], [11, 8], [11, 10], [11, 7], [11, 4], [20, 6], [20, 8], [21, 10], [22, 7], [22, 4], [22, 1], [30, 3], [30, 5], [31, 7], [33, 4], [33, 1], [40, 3], [40, 0], [40, 2], [41, 4], [44, 1], [50, 3], [50, 0], [50, 2]]

getQ: [[0, 0], [33, 1], [40, 0], [44, 1], [50, 0]]

putQ [[0, 0], [0, 1], [0, 2], [0, 3], [0, 2], [0, 1], [0, 0], [10, 1], [11, 0]]

plt.plotLine(buf.bufferMon,color='blue')