2

I am new to Python. I am writing a simulation in SimPy to model a production line, which looks like: Machine 1 -> Buffer 1 -> Machine 2 -> Buffer 2 -> and so on..

My question: I have a class, Machine, of which there are several instances. Suppose that the current instance is Machine 2. The methods of this instance affect the states of Machines 1 and 3. For ex: if Buffer 2 was empty then Machine 3 is idle. But when Machine 2 puts a part in Buffer 2, Machine 3 should be activated.

So, what is the way to refer to different instances of the same class from any given instance of that class? Also, slightly different question: What is the way to call an object (Buffers 1 and 2, in this case) from the current instance of another class?

Edit: Edited to add more clarity about the system.

2
  • 4
    You need to provide more information about how your code is structured. How does Machine 2 even know that the other machines exist at all? Commented Jul 10, 2012 at 19:25
  • 1
    Are those states shared between all machines, or does each machine have an individual one? Commented Jul 10, 2012 at 19:26

3 Answers 3

4

It is not common for instances of a class to know about other instances of the class.

I would recommend you keep some sort of collection of instances in your class itself, and use the class to look up the instances:

class Machine(object):
    lst = []
    def __init__(self, name):
        self.name = name
        self.id = len(Machine.lst)
        Machine.lst.append(self)

m0 = Machine("zero")
m1 = Machine("one")

print(Machine.lst[1].name)  # prints "one"
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks @steveha. This is exactly I was looking for. I have been coding in MATLAB, and doing something like this was quite easy there. With OOP, it's not as easy. But given all the other features of OOP, do you think there are better ways for me to do this i.e., not translating MATLAB code into Python?
Well, as discussed in other answers below, I think you should explicitly link up the objects that need to be linked. If you use @mgilson's answer or my other answer, you will have a basic framework upon which to build your simulation; it should be a clean and tidy design, and machine0 can't accidentally mess up machine99 because they won't be connected in any way.
4

This is a silly example that I cooked up where you put some data into the first machine which then moves it to the first buffer which then moves it to the second machine ...

Each machine just tags the data with it's ID number and passes it along, but you could make the machines do anything. You could even register a function to be called at each machine when it gets data.

class Machine(object):
    def __init__(self,number,next=None):
        self.number=number
        self.register_next(next)

    def register_next(self,next):
        self.next=next

    def do_work(self,data):
        #do some work here
        newdata='%s %d'%(str(data),self.number)
        if(self.next is not None):
            self.next.do_work(newdata)

class Buffer(Machine):
    def __init__(self,number,next=None):
        Machine.__init__(self,number,next=next)
        data=None

    def do_work(self,data):
        if(self.next is not None):
            self.next.do_work(data)
        else:
            self.data=data

#Now, create an assembly line
assembly=[Machine(0)]
for i in xrange(1,20):
    machine=not i%2
    assembly.append(Machine(i) if machine else Buffer(i))
    assembly[-2].register_next(assembly[-1])

assembly[0].do_work('foo')
print (assembly[-1].data)

EDIT

Buffers are now Machines too.

7 Comments

+1. For a nontrivial simulation, it might not be possible to use loops to hook up all the machines and buffers; it might be necessary to set things at least partly by hand. But I totally like the approach. I suggested something like this but I didn't show both machines and buffers; you went the extra mile here and made a very complete answer.
@steveha -- In some ways I like yours better (+1). I'm not sure that I like def register_machine(self,machine) in mine for example. (mybuff.machine=mymachine would work just fine, But, when I picture putting pieces of a machine together, it just fits as a function better than an attribute in my mind) ... I'm not sure how the API should work on this one. But anyway, we both were thinking the same thing. Of course, you thought a lot faster since you answered 20 minutes before I did and I didn't see your answer before posting mine ;) ...
Well, I have written this sort of code before. I tend to use the word "threading" to describe the process of linking them together; this could be called a "threaded simulation" perhaps.
Very cool solution @mgilson. Although not exactly what I was looking for, but for a Python/SimPy newbie like me, it provides a great example of the language's capabilities.
@user1509616 -- I keep thinking of ways to make this better. Really, Buffer should probably inherit from Machine since buffers are machines too ... Their "do_work" method should probably just be overridden to pass the data on to the next machine if it exists...
|
1

Now that you added more info about the problem, I'll suggest an alternate solution.

After you have created your machines, you might want to link them together.

class Machine(object):
    def __init__(self):
        self.handoff = None
    def input(self, item):
        item = do_something(item)  # machine processes item
        self.handoff(item)  # machine hands off item to next machine

m0 = Machine()

m1 = Machine()
m0.handoff = m1.input

m2 = Machine()
m1.handoff = m2.input

def output(item):
    print(item)

m2.handoff = output

Now when you call m0.input(item) it will do its processing, then hand off the item to m1, which will do the same and hand off to m2, which will do its processing and call output(). This example shows synchronous processing (an item will go all the way through the chain before the function calls return) but you could also have the .input() method put the item on a queue for processing and then return immediately; in this way, you could make the machines process in parallel.

With this system, the connections between the machines are explicit, and each machine only knows about the one that follows it (the one it needs to know about).

I use the word "threading" to describe the process of linking together objects like this. An item being processed follows the thread from machine to machine before arriving at the output. Its slightly ambiguous because it has nothing to do with threads of execution, so that term isn't perfect.

2 Comments

I usually think of things in this sort of a process as a "pipeline". In a lot of ways, it's similar to a shell pipeline.
"pipeline" is good because it won't be confused with "threads of execution". I used to work in FORTH, and that is sometimes called a "threaded interpreted language"; I used to have a book whose cover showed a needle, with thread behind it, linking up code blocks. :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.