Hi,--I'm trying to model a multiple parallel machines problem with only certain availability periods (defined as "q in r"). I'm using FixedDurationIntervalVar objects created for each job, machine, and availability period and set them all to be optionally performed. However, I can't get it to say that at least one of them has to be performed. The second chunk of code below is what I thought would do that but it doesn't. How can I get that to work? Thanks in advance!job_copies = {}for j in jobs:for i in machines:for q in r:name = 'job %s copy %s %s'%(j,i,q)job_copy = solver.FixedDurationIntervalVar(sa[i,q],99999,p[j],True,name)job_copies[j,i,q] = job_copy#Constrain for at least one copy to be usedfor j in jobs:solver.Add(solver.SumEquality([job_copies[j,i,q].PerformedExpr() \for i in machines\for q in r],1))
You received this message because you are subscribed to the Google Groups "or-tools-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to or-tools-discu...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
To unsubscribe from this group and stop receiving emails from it, send an email to or-tools-discuss+unsubscribe@googlegroups.com.
Hi Laurent,
Thanks for your reply. I’m not sure what you meant about “expand the constraint”, but you will find some solutions + corresponding Gant charts in the pdf attached. The horizontal axis is the time and the vertical one represents the shared available length for M0 and M1 (in this example set to L = 10 units).
The little dataset (15 jobs) I used is the following:
[[,
], …
[[3, 3],
[2, 5],
[1, 3],
[3, 7],
[7, 3],
[2, 2],
[2, 2],
[5, 5],
[10, 2],
[4, 3],
[2, 6],
[1, 2],
[6, 8],
[4, 5],
[3, 7]]
Where represents the completion time of the job
and
its minimum required length
on the CNC working area.
For the moment, I assumed that all jobs are available at t=0 and that there is no constraint on the end time (EndMax = horizon).
To establish these simple examples, I proceeded this way:
- One random sequence is generated (ex.: Sol. 2)
- I took the first piece (T5) and attributed it to M0
- I take the second piece (T7) and place it at the most left free space. Here is M1 empty (8 units length are left), so I can attributeT7 to M1.
- For the third piece (T10) however, it’s too long to be processed directly after T5 (T10 require 6 length free units, as only 5 are available once T5 is achieved). We also have to wait until T7 is completed. Then we can attribute T10 to M0 (or M1 as well).
- And so on…
For Sol. 2, it appears that the gates are inactive during 15 time units. For Sol. 3, only 5 units, and for Sol. 3’, simply by pushing T5 to the end, we achieve something pretty optimal, as only 1 time unit is wasted.
Intuitively, I would propose that
minimizing the inactive working time is equivalent to minimizing the total makespan. One
optimal lower bound should also be something like .
So I want to stack the pieces 2 by 2, as you mentioned, but without waiting that both jobs are completed to start processing a new pair of pieces. Instead, as soon as one job is achieved on one gate, we carry on with another job which fits the remaining place, even if the other gate is still working (there is no physical separation between the two gates, they’re free to translate on rails. We just want to avoid them to collide :) )
I hope my explanations are clear so far.
For the moment in implemented the cumulative constraint over length with something like this:
solver.AddConstraint(solver.Cumulative(all_tasks_flat, all_lengths_flat, length_capacity, "cumul_length"))
I guess I can do the same for the gates and consider them as a cumulative constraint:
solver.AddConstraint(solver.Cumulative(all_tasks_flat, all_number_machine_flat, tot_number_machines, "number machine"))
where all_number_machine_flat would be a list of int equal to 1 (each job require 1 gate)
and tot_number_machines will be the domain [0..2].
(By the way, I don’t get AddConstraint/Cumulative to work with dictionaries as arguments. Should the dictionaries necessarily be flattened in lists?)
I declared a list of FixedDurationInterval for each job on each machine. Where I’m stuck at, is how to set a job on “unperformed” as soon as it is already processed on one gate.
Thnak you!
To unsubscribe from this group and stop receiving emails from it, send an email to or-tools-discuss+unsubscribe@googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to or-tools-discuss+unsubscribe@googlegroups.com.
# Computes horizon.
horizon = 0
for i in all_machines:
horizon += sum(processing_times[i])
# Computes horizon.
horizon = 0
for i in all_jobs:
horizon += sum(processing_times[i])
Hi Laurent,
I'm trying to modify this jobshop (https://developers.google.com/optimization/scheduling/job_shop) to a flexible jobshop.
Could you give a python example on the usage of MapDomain() for the case you explained here?
Let's say we have two FixedDurationIntervalVars as for task A, for two possible machines:
t_a1=solver.FixedDurationIntervalVar(0,100,10,True,'task_A_on_machine_1') # I assume we need to keep the optional true
t_a2=solver.FixedDurationIntervalVar(0,100,10,True,'task_A_on_machine_2') # I assume we need to keep the optional true
and we have the following boolean variables:
b_a1=solver.BoolVar('boolean_Aon1')
b_a2=solver.BoolVar('boolean_Aon2')
How can we link them with MapDomain()?
Once we do that, how should we alter the search strategies given in (https://developers.google.com/optimization/scheduling/job_shop)?
I could not simply make use of something like this: solver.Add(t_a1.PerformedExpr() + t_a2.PerformedExpr() == 1)
Thanks
To unsubscribe from this group and stop receiving emails from it, send an email to or-tools-discuss+unsubscribe@googlegroups.com.
# We only propagate the constraint if the tasks is performed on the machine.
# model.Add(start0 == start).OnlyEnforceIf(performed_on_m0)
# model.Add(start1 == start).OnlyEnforceIf(performed_on_m0.Not())
model.AddLinearConstraint([(start0, -1), (start, 1)], 0, 0).OnlyEnforceIf(performed_on_m0)
model.AddLinearConstraint([(start1, -1), (start, 1)], 0, 0).OnlyEnforceIf(performed_on_m0.Not())
# Symmetry breaking.
# model.Add(performed[0] == 0)
zero_int = model.NewIntVar(0, 0, 'zero_int')
model.AddLinearConstraint([(performed[0], -1), (zero_int, 1)], 0, 0
To unsubscribe from this group and stop receiving emails from it, send an email to or-tools-discuss+unsubscribe@googlegroups.com.
model.Add(performed[0] == 0)Do not add the zero_int part.
--
You received this message because you are subscribed to a topic in the Google Groups "or-tools-discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/or-tools-discuss/RYLnp_0wrRk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to or-tools-discuss+unsubscribe@googlegroups.com.
Ok, how will you proceed instead? I had the same as above error with the symmetry breaking:model.Add(performed[0] == 0)
model.AddLinearConstraint([(performed[0], 1), 0, 0)