Solved

Machine shop scheduling problem, how to introduce a binaray variable that shows if you have production?

  • 16 July 2022
  • 7 replies
  • 107 views

Dear all,

I'm quite new to Aimms, therefore I don’t know if my problem is easy to solve or a difficult one. My end goal is to be able to generate an automated production planning for a big pizza bakery. The machine shop scheduling example is in the direction for what I’m looking for, see the link below. 

https://how-to.aimms.com/Articles/473/473-ProductionPlanning-machinescheduling.html

The machine shop scheduling example determines the optimal machine and start time for each order, so that the makespan is minimized. 

I want to expand this model, so that more contraints can be added. An important binary variable for me is ‘DoYouHaveProductionInAPeriod(i,o,i_hc)’: do you have production at a certain machine i, for a spefic order o, at a certain time period i_hc. An example of a constraint that I want to add and using the variable ‘DoYouHaveProductionInAPeriod(i,o,i_hc)’ is if I have 4 workers available, only 4 machines can run at the same time → for each i_hc, sum((i,o),DoYouHaveProductionInAPeriod(i,o,i_hc) <= 4. 

But how do generate the variable ‘DoYouHaveProductionInAPeriod(i,o,i_hc)’?

In my mind it should be possible, because the binary variable StartProductionOnProductionLine(i,o,i_hc) indicates when production starts and the parameter ActivityLength(i,o) states the duration of an order o on a specific machine i.

I was thinking of adding a constraint, which only works at time i_hc when StartProductionOnProductionLine(i,o,i_hc) is 1: sum((i_hc1)| (i_hc1>= (StartProductionOnProductionLine(i,o,i_hc)*i_hc1) and i_hc1<= StartProductionOnProductionLine(i,o,i_hc)*(i_hc1+ActivityLength(i,o))), DoYouHaveProductionInAPeriod(i,o,i_hc))=ActivityLength(i,o)

But I got an error: There is no operation defined for operator "*" with arguments of data type numeric and data type element; the arguments themselves are "StartProductionOnProductionLine(i,o,i_hc) $ domStartProductionProductionLine(i,o,i_hc)" and "i_hc1".

Who can help me to define the binary variable  ‘DoYouHaveProductionInAPeriod(i,o,i_hc)’? Is it possible or not?

 

 

icon

Best answer by luispinto 18 July 2022, 11:30

View original

7 replies

Userlevel 4
Badge +5

Hello Harm,

I see this is your first post, so let me first off welcome you to our community :)

Some pointers I can already see:

  1. You cannot use your variable StartProductionOnProductionLine as a condition of the sum, as you are trying to do within your constraint. This would be very non-linear modelling and I believe this is a MIP model.
  2. If you want to use i_hcl as you are doing so, please make sure to make to make the set a subset of integers. This way you will be able to directly place it in an expression.

 

Additionally, I would seek out a formulation that will “force” your DoYouHaveProductionInAPeriod to be one based on if there is production starting in this period or some previous period, but you still have production happening. Since I don't know the model, this is just a rough idea.

DoYouHaveProductionInAPeriod(i_hcl) >= StartProductionOnProductionLine(i_hcl) + StartProductionOnProductionLine(i_hcl-1) +...

(the second StartProductionOnProductionLine is only if it takes 2 periods to produce the product, hence it will still be going at i_hcl).

 

I hope this helps you get started off.

 

Hi Luispinto,

Thank you for replying. I'm learning how to use Aimms, so maybe I ask stupid questions. 1. You cannot use variables in a condition of a sum. Thank you, I didn't know that. Indeed, this is a MILP problem. 2. i_hc, i_hc1, i_hc2 are an index for the hour calender of the machines. So if you want to use the index more versitale, make it an interger. Ok, thank you.

I learn a lot from examples, therefore I’m going to use them here.  

For example, if you have only 1 machine and 2 orders and the result of the MILP for StartProductionOnProductionLine(o,i_hcl) is:

Time period (i_hc):                                        0 1 2 3 4 5 6 7 8 9 10

StartProductionOnProductionLine(1, i_hcl): 0 1 0 0 0 0 0 0 0 0  0

StartProductionOnProductionLine(2, i_hcl): 0 0 0 0 0 0 1 0 0 0  0

ActivityLength(1) := 3

ActivityLength(2) := 4

The DoYouHaveProductionInAPeriod(i_hcl) then must look like this:

Time period (i_hc):                                        0 1 2 3 4 5 6 7 8 9 10

DoYouHaveProductionInAPeriod(i_hcl)        0 1 1 1 0 0 1 1 1 1  0

 

If I implement your solution (DoYouHaveProductionInAPeriod(o,i_hcl) >= StartProductionOnProductionLine(o, i_hcl) + StartProductionOnProductionLine(o, i_hcl-1) +...).

For order 1 it would be DoYouHaveProductionInAPeriod(1,i_hcl) >= StartProductionOnProductionLine(1, i_hcl) + StartProductionOnProductionLine(1, i_hcl-1) + StartProductionOnProductionLine(1, i_hcl-2)

For order 2 it would be DoYouHaveProductionInAPeriod(2,i_hcl) >= StartProductionOnProductionLine(2, i_hcl) + StartProductionOnProductionLine(2, i_hcl-1) + StartProductionOnProductionLine(2, i_hcl-2) + StartProductionOnProductionLine(2, i_hcl-3)

 

Time period (i_hc):                                        0 1 2 3 4 5 6 7 8 9 10

DoYouHaveProductionInAPeriod(1, i_hcl)    0 1 1 1 0 0 0 0 0 0  0

DoYouHaveProductionInAPeriod(2, i_hcl)    0 0 0 0 0 0 1 1 1 1  0

 

This looks like the result I want to see. Thank you very much!!!

Hi Luispinto,

This is what I used for the constraint:

sum((i_hc2)| (i_hc2>= (i_hc - ActivityLengthM1(i,o))) and (i_hc2>= begHourCal) and (i_hc2 <= i_hc),  StartProductionOnProductionLine(i,o,i_hc2)) = DoYouHaveProductionInAPeriod(i,o,i_hc)

Some questions:

The hour calender starts at 2016-05-09 00. This is when order 7 starts. Why is the hour calender for the variable DoYouHaveProductionInAPeriod(i,o,i_hc) not showing hours 00, 01, 02 and 04.

 

Other question is about using the equal sign (=) and greater than (>=) in the constraint. The optimal solution had a difference. When using the equal sign the result was 126. When using the greater than the result was 116. So, the preference is to us >= sign. But the variable had no Upper Bound → Variable was not restricted and didn't show the correct result. So I added the UB, but then I got the 126 result again. So what to do?

I solved the first question → the condition in the constraint ensured that i_hc got out of bound (time period was not in the HourCalender). I created a new parameter, that compensates when i_hc gets out of bound, which has the name CompensateOutOfBoundHourCalender(i,o,i_hc). For example, when i_hc is the second time period, and the activity length is 5 → 2-5 = -3 (out of bound). CompensateOutOfBoundHourCalender in this case will be 3. Then you have 2+3-5 = 0, you remain in bounds. 

The constraint then will be the following:

sum((i_hc2)| (i_hc2>= (i_hc + CompensateOutOfBoundHourCalender(i,o,i_hc) - ActivityLengthM1(i,o))) and (i_hc2 <= i_hc),  StartProductionOnProductionLine(i,o,i_hc2)) = DoYouHaveProductionInAPeriod(i,o,i_hc)

Userlevel 4
Badge +5

Dear Harm,

Sorry for the late reply.

On the “=” vs “>=” question, it depends on what is meant to happen.

Looking at your constraint:

sum((i_hc2)| (i_hc2>= (i_hc + CompensateOutOfBoundHourCalender(i,o,i_hc) - ActivityLengthM1(i,o))) and (i_hc2 <= i_hc),  StartProductionOnProductionLine(i,o,i_hc2)) = DoYouHaveProductionInAPeriod(i,o,i_hc)

 

If we use the = sign, you are defining that DoYouHaveProductionInAPeriod has to be exactly 0 or 1 depending on if the previous periods had something start.

If you use the >= sign, you defining that DoYouHaveProductionInAPeriod has to be 0 when the left hand side is 0, and can be either 1 or 0 if the left hand side is 1.

If you use the <= sign, you defining that DoYouHaveProductionInAPeriod has to be 1 when the left hand side is 1, and can be either 1 or 0 if the left hand side is 0.

Which one suits your representation.

Btw., I do believe that you defined DoYouHaveProductionInAPeriod as binary, correct?

DoYouHaveProductionInAPeriod as binary, correct? Yes, it is a binary variable. It needs to be ‘=’, because If you have production in a certain time period, I want it to show with 1. And if there is no production, I want to see 0. Which solution is better?

Solution 1 is using 1 constraint with the ‘=’, sum((i_hc2)| (i_hc2>= (i_hc + CompensateOutOfBoundHourCalender(i,o,i_hc) - ActivityLengthM1(i,o))) and (i_hc2 <= i_hc),  StartProductionOnProductionLine(i,o,i_hc2)) = DoYouHaveProductionInAPeriod(i,o,i_hc)

Solutioon 2 is using two constraints with >= and <= sum((i_hc2)| (i_hc2>= (i_hc + CompensateOutOfBoundHourCalender(i,o,i_hc) - ActivityLengthM1(i,o))) and (i_hc2 <= i_hc),  StartProductionOnProductionLine(i,o,i_hc2)) >= DoYouHaveProductionInAPeriod(i,o,i_hc)

sum((i_hc2)| (i_hc2>= (i_hc + CompensateOutOfBoundHourCalender(i,o,i_hc) - ActivityLengthM1(i,o))) and (i_hc2 <= i_hc),  StartProductionOnProductionLine(i,o,i_hc2)) <= DoYouHaveProductionInAPeriod(i,o,i_hc)

 

Userlevel 4
Badge +5

In practice, they are equivalent, but I can only imagine that the first solution is better, since it makes for a smaller model.

By the way, I believe that Solvers will probably identify solution 2 and automatically transform it to solution 1.

Reply


Didn't find what you were looking for? Try searching on our documentation pages:

AIMMS Developer & PRO | AIMMS How-To | AIMMS SC Navigator