Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variable length task? #61

Open
glibersat opened this issue Sep 9, 2018 · 9 comments
Open

Variable length task? #61

glibersat opened this issue Sep 9, 2018 · 9 comments

Comments

@glibersat
Copy link

Hi,

First of all, thanks for this wonderful piece of code!
I've managed to modelize almost all my needs except one case. Is there a way to either:

  • have a variable task that can be dynamically extended to the beginning of its following?
  • block a resource until the next task is scheduled?

To understand my scenario, here's the use case:

  • we brew (1 day)
  • we ferment (~15 days)
  • and we bottle condition as soon as we're available

[Brew/R=brewhouse] <= [Ferment/R=Tank1] <..[variable length task/R=Tank1]..< [Bottle condition/R=Tank1+Capper]

The problem is that sometimes, we are busy or it's sunday and we want to wait a few days before bottle conditioning. How would you achieve that? Thank you!

@timnon
Copy link
Owner

timnon commented Sep 10, 2018

Hi, nice to hear that pyschedule is used to brew beer!

Regarding your problem, you could use some capacity constraint like setting:

Ferment.block = 1
Bottle.block = -1
For t in range(horizon):
Tank1['block'][:t] <= 1

This would ensure that some bottle operation needs to take place before a new ferment is started.

You probably also want to ensure that the fermenting and bottleling are happening at the same tank for one beer. This works like Bottle >= Ferment*Tank1

If you have a concrete example, i could try to fix it, i am always looking for real-life examples to showcast.

@glibersat
Copy link
Author

Thank you for you quick answer!

I've tried using the block strategy but I still experience 2 fermentations being scheduled one after the other then two bottling jobs. Weird!

I already had added a "same tank" constraint, that works quite well! But I did that using:
bottling += fermentation * fermenters_all
do you think that's correct?

Give me a few days to clean up my mess and I'll send you a link to the code. I'll be quite happy if you can help me fix the latest "bugs" and of course, you can use it as a showcast :)

Cheers!

@timnon
Copy link
Owner

timnon commented Sep 11, 2018

Maybe you should also constrain the number of bottle operations in a row by using
Tank1['block'][:t] >= -1
? But this should more be a problem the other way round, happy to take a look

@glibersat
Copy link
Author

I've created a gist for you to read my (very dirty) code. Sorry for the quality, it's really a poc:
https://gist.github.com/glibersat/c5a487178a7e6b82102aaa1a6066dd09

I hope it's clear enough, feel free to ask for informations where it's not understandable.

Thank you very much!

@glibersat
Copy link
Author

Unfortunately, the constraint is still not working. See attached picture: multiple fermentations take place in tanks before bottling/transfer order (example: Tank "funky" and fermentations of "Fut Papayou" and "Yoga").
capture d ecran de 2018-09-11 23-05-20

@timnon
Copy link
Owner

timnon commented Sep 12, 2018

Had a quick look on my phone and spotted the following syntactic problem. You need to write

S += fermenter['block'][:t] <= 1

Otherwise, the constraint is created but not added to the scenario. Please check if that gives some progress. I will be able to run your code next sunday.

@glibersat
Copy link
Author

My bad, I didn't know I had to add it. Now it works, in the expected order, thank you! Took about 50minutes but the result is good :)
I'll now start cleaning a little bit and try to implement extra things after that.

@timnon
Copy link
Owner

timnon commented Sep 13, 2018

Excellent. If you have performance problems, check the option a “group“ interchangeable tasks, if you have any. I will have a look.

@timnon
Copy link
Owner

timnon commented Sep 23, 2018

Had a look at the gist above, some comments:

  • you can define chambre_garde = S.Resource('chambre_garde', size=7) to group these resources, this drops the computation time.
  • your can set e.g.
plot_color = ColorHash(name).hex
brewday = S.Task('{0}_brewday'.format(name),plot_color=plot_color)

to color all tasks in one batch with the same color. You can then plot without text using plotters.matplotlib.plot(S,show_task_labels=False,fig_size=(10,5)) to get better visuals right away.

  • for testing, it is quite handy to use a ratio_gap like solvers.mip.solve(S, kind="CBC", time_limit=3000, ratio_gap=1.2, msg=1). This will e.g. stop the computation as soon as a solution is found, which is provably only 20% off an optimal one

Looks like an awesome project, happy to see some newer version if available

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants