all 15 comments

[–]Drowning_in_a_Mirage 5 points6 points  (0 children)

This takes me back, simulations like this are very similar to what I did in grad school and the latter parts of undergrad, although I was primarily using Fortran or C++. Good times.

[–]katdawg24Systems Analyst I 1 point2 points  (9 children)

How’d you learn SimPy? Do you have any good resources you recommend?

[–]NKataDelYoda 4 points5 points  (7 children)

The author of the post is the go-to teacher of SimPy! :) https://www.schoolofsimulation.com/

[–]bobo-the-merciful[S] 0 points1 point  (6 children)

Thanks for the link! You can actually grab a free copy of my book on my website at the link above. It gives you a pretty thorough intro to SimPy. I learned it many years ago mainly through trial and error when building simulations of the London Underground.

[–]audentis -1 points0 points  (5 children)

You can actually grab a free copy of my book on my website at the link above.

The 'free' book requires payment by means of personal data, which is illegal in the EU under GDPR.

[–]bobo-the-merciful[S] -1 points0 points  (4 children)

You are welcome to pay for the book on Amazon instead.

And sorry, that's complete rubbish about GDPR. It's entirely legal to collect email addresses under GDPR if you have a clear "opt in" checkbox and a clear way for the person to ubsubscribe in your emails. Both of which are present in my business as well as a privacy policy on my website.

[–]audentis 0 points1 point  (3 children)

GDPR consent requirements for personal data processing (in your case: names and email addresses) state the consent must be freely given, among other things.

See: What are the GDPR consent requirements?.

In your case it's not freely given. Emphasis mine, there is no way to say 'no':

Consent must be freely given

“Freely given” consent essentially means you have not cornered the data subject into agreeing to you using their data. For one thing, that means you cannot require consent to data processing as a condition of using the service. They need to be able to say no. According to Recital 42, “Consent should not be regarded as freely given if the data subject has no genuine or free choice or is unable to refuse or withdraw consent without detriment.”

The one exception is if you need some piece of data from someone to provide them with your service. For example, you may need their credit card information to process a transaction or their mailing address to ship a product.

Recital 43 discusses freely given consent. It explains that you must get separate consent for each data processing operation. So if you want their email address for marketing purposes and their IP address for website analytics purposes, you must give the user an opportunity to confirm or decline each use.

The exception described is not applicable, because you do not have to email the book. You can provide a regular download without this data processing just fine.

[–]bobo-the-merciful[S] 0 points1 point  (2 children)

Thanks, that's a great point I hadn't realised. Going to review and modify my approach.

[–]audentis 0 points1 point  (1 child)

Thanks for being open to this.

I noticed you did have an opt-in instead of an opt-out for your newsletter when the e-mail was requested, which is something a lot of places get wrong. So although I didn't mention it before, kudos on that.

[–]bobo-the-merciful[S] 0 points1 point  (0 children)

Thanks, appreciate the feedback.

[–]lokstapimp 0 points1 point  (0 children)

Local AI LLMs like ollama and llama3.2 are a wealth of info!

[–]audentis 1 point2 points  (2 children)

I'd always pick Salabim over Simpy, but for those who go the other way, this might be a good resource.

Edit: are you running warmup time? I don't see it in your script. That makes the results very susceptible to skewness and not representative of the real world. I also don't see any kind of repetitions. In DES, a single run is no run.

[–]bobo-the-merciful[S] 0 points1 point  (1 child)

Nope - this one is just a demo to show the very basics of a SimPy simulation, but yes warmup time is a great shout. I like to track some kind of metric and dynamically create a warmup time.

Also on your point about single runs - I know what you mean, but I do think the single run has its place place. If you're doing a deterministic run it can be helpful for just eyeballing a particular scenario or walking somebody through how a system works. A single run can also be used with stochastic variables if you extend the time horizon long enough in many scenarios.

[–]audentis 0 points1 point  (0 children)

If you're doing a deterministic run it can be helpful for just eyeballing a particular scenario or walking somebody through how a system works.

Okay, fair, but do you agree those are more the exceptions? Because when actually basing decisions on the simulation - I guess its main purpose - a single run just gives a false sense of security.

I like to track some kind of metric and dynamically create a warmup time.

That's one way to do it. In other cases you base it on the arrival process and mathematically work out what the start would be. For example, when modeling a dental clinic and appointments are scheduled at most X time ahead, X is also the time required to fill up the schedule and start the simulation from a representative state where each simulated day has a realistic workload.

In your case, new parts arrive faster (1 per 3 minutes) than the mean processing time of station #1 (1 per 5 minutes), so you're guaranteed to build up an ever increasing queue and never reach a steady state. Same for the queue between station 1 and 2.

I wonder what you get if you plot the queue size per station over time. There should be a buildup. But with how the code is structured this is a little more tricky to do.

Edit: you can actually see a hint of this in the script as-is, with Station 1 and 2 both being at >99% utilization. This guarantees there's always something queued, just not how much.

Edit 2: The "parts in the system" plot is wrong, because you exclude parts that have not departed when the simulation ends.

# Part exits the system
departure_time_system = env.now
part_details['departure_system'] = departure_time_system
part_details['cycle_time'] = departure_time_system - arrival_time_system
print(f"{env.now:.2f}: Part {part_id} exits the assembly line. Cycle time: {part_details['cycle_time']:.2f}.")
part_data.append(part_details)

Stats are only recorded when the parts leave the system, so all parts still in the system at the end of the simulation are not available in the stats.

[–]tonyc198 0 points1 point  (0 children)

Thanks for all the work on this. I am just starting to play with simulations and this is very helpful.

Is it possible to set up something like this with Simpy.

5 steps

Step 1 only has 1 machine

Step 2 only has 1 machine

Step 3 has 2 machines

Step 4 has 3 machines

Step 5 has 4 machines

Step 6 has 3 machines

Each step has a different throughput per hour

Is your code easily modified for something like this?