google / or-tools

Google's Operations Research tools:
https://developers.google.com/optimization/
Apache License 2.0
11.28k stars 2.13k forks source link

HELP: Split tasks in jobShop like problem #1223

Closed gustavo-barros closed 5 years ago

gustavo-barros commented 5 years ago

Hi,

I'm trying to solve a jobShop like problem for a factory floor operations scheduling. I'm using CPSolver.

The problem is that I have a factory Plant that works on a set of predefined work shifts. Each machine can have it's own work shift for each day of the calendar. So I configure the model to distribute the tasks only in the allowed time period.

The difficult part happens when there is a task length that exceeds the length of the available work shift time. The solver simply move the entire task to the next day shift or next allowed time space. So I was wondering, is there a way to make the solver split the task between two work shifts?

See the image below, the orange blocks are the allowed ones defined in the machine shift for that specific day. The purple ones are not allowed to be used because is the time that the factory shutdown. The blue block (30002/1) for example is a block that I wanted to be splitted, because it has no dependencies and there is a free space at it's left as shown in the image:

image

After this procedure, the result should be something like this image below, and this behaviour should be applied to each task that fits in this case and are longer than the available space:

image

lperron commented 5 years ago

Pre-compute which tasks can be splitted, create more than 1 intervals. (2 in your case), constraint the sum of durations to be the total duration. Do you need something else ?

And as I said in another mail, please use the CP-SAT solver. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le ven. 26 avr. 2019 à 21:15, gustavo-barros notifications@github.com a écrit :

Hi,

I'm trying to solve a jobShop like problem for a factory floor operations scheduling. I'm using CPSolver.

The problem is that I have a factory Plant that works on a set of predefined work shifts. Each machine can have it's own work shift for each day of the calendar. So I configure the model to distribute the operations only in the allowed time period.

The difficult part happens when there is a operation length that exceeds the length of the available work shift time. The solver simply move the entire operation to the next day shift or next allowed time space. So I was wondering, is there a way to make the solver split the operation between two work shifts?

See the image below, the orange blocks are the allowed ones defined in the machine shift for that specific day. The purple ones are not allowed to be used because is the time that the factory shutdown. The blue block (30002/1) for example is a block that I wanted to be splitted, because it has no dependencies and there is a free space at it's left as shown in the image:

[image: image] https://user-images.githubusercontent.com/36746102/56830314-67c80900-683c-11e9-991a-eb3800b482b9.png

After this procedure, the result should be something like this image below, and this behaviour should be applied to each operation that fits in this case and are longer than the available space:

[image: image] https://user-images.githubusercontent.com/36746102/56830402-9d6cf200-683c-11e9-9170-1df064f69175.png

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3PHNQUNJQTLACP4YYTPSNIDPANCNFSM4HIZUSHA .

EduSikora commented 5 years ago

Pre-compute which tasks can be splitted, create more than 1 intervals. (2 ...

@lperron Does this mean that we will need to split every task by a single unit of time and group them using a constraint?

Ie: task that lasts 3 units of time, will turn into 3 tasks of 1 unit of time each??

What if we have 5000 tasks? Won’t the solver take a long time to solve?

I don’t know if I understood your answer correctly.. any simple example code would be much appreciated..

Thanks!!

Sent with GitHawk

lperron commented 5 years ago

no, if a task duration is less than <= 2 x the smallest time span, split it in 2. Force the duration of the first interval to be at least one. Make the second optional. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le sam. 27 avr. 2019 à 15:22, EduSikora notifications@github.com a écrit :

Pre-compute which tasks can be splitted, create more than 1 intervals. (2 ...

@lperron https://github.com/lperron Does this mean that we will need to split every task by a single unit of time and group the using a constraint?

Ie: task that lasts 3 units of time, will turn into 3 tasks of 1 unit of time each??

What if we have 5000 tasks? Won’t the solver take a long time to solve?

I don’t know if I understood your answer correctly.. any simple example code would be much appreciated..

Thanks!!

Sent with GitHawk http://githawk.com

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223#issuecomment-487285829, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3KEVG2HTBJDODEB5PDPSRHRVANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

Hi Iperron,

Thank you for your reply.

I didn't understand your solution. The problem is that we can only know if a task should be splitted after it was distributed using the solver. We are trying to avoid running the solver, making adjustments and running it again. We need to be efficient.

If we pre-compute, we would not know wich one to split in advance. And even if we apply a splitting logic over all tasks at the beginning we would end up with thousands of tasks, at least the double of the total amount, right? Because most of then have length <= 2xSmallestTimeSpan. That's probably would be impractical because we want to tackle large problems.

How can we achieve this behaviour using the solver?

image

We are currently setting the disabled periods (purple) like this:

image

where: image and

key = startTime deactivatedPeriod = duration.

Then we run this: image

image

Where:

_DataProcessor.GetOdfsCount() returns the jobs count

So the solver knows where not to put the tasks. There is another way that would help we achieve the mentioned behaviour? Or this would not change anything?

We need this functionallity to be able to use ORTools solver in our project.

lperron commented 5 years ago

In previous threads on the mailing list, I discussed the options for having tasks spanning across breaks. That is a task interrupted by a break would resume as soon as the breaks stop ?

Would you be interested in that ?

Now, about the split green block. You could force all blocks to belong to different break structure. For instance impose a min distance between split tasks, or having one optional tasks per work period and per task.

You also post-process the solution to merge the green blocks.

Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le lun. 29 avr. 2019 à 15:50, gustavo-barros notifications@github.com a écrit :

Hi Iperron,

Thank you for your reply.

I didn't understand your solution. The problem is that we can only know if a task should be splitted after it was distributed using the solver. We are trying to avoid running the solver, making adjustments and running it again. We need to be efficient.

If we pre-compute, we would not know wich one to split in advance. And even if we apply a splitting logic over all tasks at the beginning we would end up with thousands of tasks, at least the double of the total amount, right? Because most of then have length <= 2xSmallestTimeSpan. That's probably would be impractical because we want to tackle large problems.

How can we achieve this behaviour using the solver?

[image: image] https://user-images.githubusercontent.com/36746102/56898389-4d25a800-6a67-11e9-8459-9db053c61581.png

We are currently setting the disabled periods (purple) like this:

[image: image] https://user-images.githubusercontent.com/36746102/56899290-7c3d1900-6a69-11e9-9686-6993b9d5f8ce.png

where: [image: image] https://user-images.githubusercontent.com/36746102/56899416-c1f9e180-6a69-11e9-8dcc-590fedaa9808.png and

key = startTime deactivatedPeriod = duration.

Then we run this: [image: image] https://user-images.githubusercontent.com/36746102/56899985-2b2e2480-6a6b-11e9-9394-6b0b78987235.png

[image: image] https://user-images.githubusercontent.com/36746102/56899944-0fc31980-6a6b-11e9-8550-d34ab3cf1910.png

Where:

_DataProcessor.GetOdfsCount() returns the jobs count

So the solver knows where not to put the tasks. There is another way that would help we achieve the mentioned behaviour? Or this would not change anything?

We need this functionallity to be able to use ORTools solver in our project.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223#issuecomment-487587340, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3NHFWYINSVCYH3A6I3PS34K3ANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

That is a task interrupted by a break would resume as soon as the breaks stop ?

That's exactly what we need. Look at machine_0 in the image. See the purple (1 hour length) break interval after the first orange interval. That's a lunch break for example. So if a worker start a task in the first orange interval and leaves for lunch, it stops the task while lunch break and resume after the worker come back from the lunch time. The same happen when the task is longer than the day shift, it must resume in the next shift. That's the behaviour we want.

How can we do that?

lperron commented 5 years ago

Can you look at:

https://groups.google.com/forum/?hl=en#!searchin/or-tools-discuss/FlexibleJobShop$20with$20Machine$20Calendars%7Csort:date/or-tools-discuss/DA_4Pniwhn8/BH2vO5K1BgAJ

The last message in the thread is, IMO, the best option, It requires pre-processing, but it should work.

Above, you have the second option with split intervals.

Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le lun. 29 avr. 2019 à 17:19, gustavo-barros notifications@github.com a écrit :

That is a task interrupted by a break would resume as soon as the breaks stop ?

That's exactly what we need. Look at machine_0 in the image. See the purple (1 hour length) break interval after the first orange interval. That's a lunch break for example. So if a worker start a task in the first orange interval and leaves for lunch, it stops the task while lunch break and resume after the worker come back from the lunch time. That's the behaviour we want.

How can we do that?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223#issuecomment-487622611, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3IEY327OVAY6GCJ5JLPS4GZJANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

Hey Laurent,

I tried to implement that idea with no success. I don't know if I grasp the idea correctly. This was my try: image

Doing this I reached a no solution answer.

I didn't understand how it could split the tasks when there is a deactivated shift. How those dx parameters are set? Is during the solver running process?

I'm hitting a dead end here :(

I understand that "start" is all possible start states, "duration" is the range that durations can vary and "end" is the range where it can end, starting from 0 to 20 (max) in your case example; Then you create those boolean dx's variables.

image

and here seems you are setting constraints to set the booleans variables to true if they are attended, for example: if a task starts at any number between and including [0..1] U [14..15], d4 will be activated to true as says this constraint image

and then it will set the task duration to 4 because d4 is true as image

Is there any sense in what I told, or I completely miss the point? I need your help to understand this.

lperron commented 5 years ago

at the minimum, intervals should be non-overlapping. But this would not change the unsat part. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le lun. 29 avr. 2019 à 21:07, gustavo-barros notifications@github.com a écrit :

Hey Laurent,

I tried to implement that idea with no success. I don't know if I grasp the idea correctly. This was my try: [image: image] https://user-images.githubusercontent.com/36746102/56917475-f4b7d000-6a91-11e9-87df-d4371348eb5a.png

Doing this I reached a no solution answer.

I didn't understand how it could split the tasks when there is a deactivated shift. How those dx parameters are set? Is during the solver running process?

I'm hitting a dead end here :(

I understand that "start" is all possible start states, "duration" is the range that durations can vary and "end" is the range where it can end, starting from 0 to 20 (max) in your case example; Then you create those boolean dx's variables.

[image: image] https://user-images.githubusercontent.com/36746102/56919958-5713cf00-6a98-11e9-8cc0-9632d8aaaba0.png

and here seems you are setting constraints to set the booleans variables to true if they are attended, for example: if a task starts at any number between and including [0..1] U [14..15], d4 will be activated to true as says this constraint [image: image] https://user-images.githubusercontent.com/36746102/56919676-9e4d9000-6a97-11e9-92fe-81b2005d8660.png

and then it will set the task duration to 4 because d4 is true as [image: image] https://user-images.githubusercontent.com/36746102/56919802-e7054900-6a97-11e9-8e23-771585debadd.png

Is there any sense in what I told, or I completely miss the point? I need your help to understand this.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223#issuecomment-487704993, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3MAOIPXUZFQJA5JOT3PS5BPJANCNFSM4HIZUSHA .

lperron commented 5 years ago

Read the doc on NewEnumeratedIntVar, you need a flattened list on interval.

{1, 2, 3, 5, 7, 8, 9} is written as [1, 3, 5, 5, 7, 9]

Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le lun. 29 avr. 2019 à 21:11, Laurent Perron lperron@google.com a écrit :

at the minimum, intervals should be non-overlapping. But this would not change the unsat part. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le lun. 29 avr. 2019 à 21:07, gustavo-barros notifications@github.com a écrit :

Hey Laurent,

I tried to implement that idea with no success. I don't know if I grasp the idea correctly. This was my try: [image: image] https://user-images.githubusercontent.com/36746102/56917475-f4b7d000-6a91-11e9-87df-d4371348eb5a.png

Doing this I reached a no solution answer.

I didn't understand how it could split the tasks when there is a deactivated shift. How those dx parameters are set? Is during the solver running process?

I'm hitting a dead end here :(

I understand that "start" is all possible start states, "duration" is the range that durations can vary and "end" is the range where it can end, starting from 0 to 20 (max) in your case example; Then you create those boolean dx's variables.

[image: image] https://user-images.githubusercontent.com/36746102/56919958-5713cf00-6a98-11e9-8cc0-9632d8aaaba0.png

and here seems you are setting constraints to set the booleans variables to true if they are attended, for example: if a task starts at any number between and including [0..1] U [14..15], d4 will be activated to true as says this constraint [image: image] https://user-images.githubusercontent.com/36746102/56919676-9e4d9000-6a97-11e9-92fe-81b2005d8660.png

and then it will set the task duration to 4 because d4 is true as [image: image] https://user-images.githubusercontent.com/36746102/56919802-e7054900-6a97-11e9-8e23-771585debadd.png

Is there any sense in what I told, or I completely miss the point? I need your help to understand this.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223#issuecomment-487704993, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3MAOIPXUZFQJA5JOT3PS5BPJANCNFSM4HIZUSHA .

KorpEduardoSikora commented 5 years ago

Hi @lperron,

We're trying to understand and implement what you're saying, and at the same time we're learning about the OR Tools and its solver functionality.

Is there any tool (ie: skype) that we can chat in 'real-time'? Maybe we can share our screen too.. I sent you a message on what I believe it's your skype's account.

We really need this functionality or the Google OR Tools will not fit our project needs..

at the minimum, intervals should be non-overlapping. But this would not change the unsat part. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00 Le lun. 29 avr. 2019 à 21:07, gustavo-barros notifications@github.com a écrit : Hey Laurent, I tried to implement that idea with no success. I don't know if I grasp the idea correctly. This was my try: [image: image] https://user-images.githubusercontent.com/36746102/56917475-f4b7d000-6a91-11e9-87df-d4371348eb5a.png Doing this I reached a no solution answer. I didn't understand how it could split the tasks when there is a deactivated shift. How those dx parameters are set? Is during the solver running process? I'm hitting a dead end here :( I understand that "start" is all possible start states, "duration" is the range that durations can vary and "end" is the range where it can end, starting from 0 to 20 (max) in your case example; Then you create those boolean dx's variables. [image: image] https://user-images.githubusercontent.com/36746102/56919958-5713cf00-6a98-11e9-8cc0-9632d8aaaba0.png and here seems you are setting constraints to set the booleans variables to true if they are attended, for example: if a task starts at any number between and including [0..1] U [14..15], d4 will be activated to true as says this constraint [image: image] https://user-images.githubusercontent.com/36746102/56919676-9e4d9000-6a97-11e9-92fe-81b2005d8660.png and then it will set the task duration to 4 because d4 is true as [image: image] https://user-images.githubusercontent.com/36746102/56919802-e7054900-6a97-11e9-8e23-771585debadd.png Is there any sense in what I told, or I completely miss the point? I need your help to understand this. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#1223 (comment)>, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3MAOIPXUZFQJA5JOT3PS5BPJANCNFSM4HIZUSHA .

lperron commented 5 years ago

No, I have no time for chat, and I am on vacation.

Have you read:

https://github.com/google/or-tools/blob/master/ortools/sat/doc/integer_arithmetic.md

and more generally

https://github.com/google/or-tools/blob/master/ortools/sat/doc/README.md

(it seems github markdown rendering is down though).

Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le lun. 29 avr. 2019 à 22:04, KorpEduardoSikora notifications@github.com a écrit :

Hi @lperron https://github.com/lperron,

We're trying to understand and implement what you're saying, and at the same time we're learning about the OR Tools and its solver functionality.

Is there any tool (ie: skype) that we can chat in 'real-time'? Maybe we can share our screen too.. I sent you a message on what I believe it's your skype's account.

We really need this functionality or the Google OR Tools will not fit our project needs..

at the minimum, intervals should be non-overlapping. But this would not change the unsat part. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00 Le lun. 29 avr. 2019 à 21:07, gustavo-barros notifications@github.com a écrit : … <#m-161962866676888796> Hey Laurent, I tried to implement that idea with no success. I don't know if I grasp the idea correctly. This was my try: [image: image] https://user-images.githubusercontent.com/36746102/56917475-f4b7d000-6a91-11e9-87df-d4371348eb5a.png Doing this I reached a no solution answer. I didn't understand how it could split the tasks when there is a deactivated shift. How those dx parameters are set? Is during the solver running process? I'm hitting a dead end here :( I understand that "start" is all possible start states, "duration" is the range that durations can vary and "end" is the range where it can end, starting from 0 to 20 (max) in your case example; Then you create those boolean dx's variables. [image: image] https://user-images.githubusercontent.com/36746102/56919958-5713cf00-6a98-11e9-8cc0-9632d8aaaba0.png and here seems you are setting constraints to set the booleans variables to true if they are attended, for example: if a task starts at any number between and including [0..1] U [14..15], d4 will be activated to true as says this constraint [image: image] https://user-images.githubusercontent.com/36746102/56919676-9e4d9000-6a97-11e9-92fe-81b2005d8660.png and then it will set the task duration to 4 because d4 is true as [image: image] https://user-images.githubusercontent.com/36746102/56919802-e7054900-6a97-11e9-8e23-771585debadd.png Is there any sense in what I told, or I completely miss the point? I need your help to understand this. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#1223 (comment) https://github.com/google/or-tools/issues/1223#issuecomment-487704993>, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3MAOIPXUZFQJA5JOT3PS5BPJANCNFSM4HIZUSHA .

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223#issuecomment-487723264, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3IO5SF6EZ2X4MF5PV3PS5IGFANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

Hi Laurent,

Sorry to bother you in your vacation. But this is very important to us, if you could help we will really appreciate it. I read all the examples you sent me, studied it and made several trials and errors here but something seems not to fit. There is something missing. Could you send me an example code related to our problem? So that it could enlight the path for us?

Our first valid shift is: [8..12] U [13..18]

If we could simply simulate the case in wich a task starts at 11, stops at 12 and resume at 13 would be enough for us to continue.

lperron commented 5 years ago

I have pushed

https://github.com/google/or-tools/blob/master/ortools/sat/samples/scheduling_with_calendar_sample_sat.py

Which outputs

start=8 duration=3 across=0

start=9 duration=3 across=0

start=10 duration=3 across=0

start=11 duration=4 across=1

start=12 duration=4 across=1

start=14 duration=3 across=0

start=15 duration=3 across=0

It should be easy to adapt to other languages. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le mar. 30 avr. 2019 à 14:18, gustavo-barros notifications@github.com a écrit :

Hi Laurent,

Sorry to bother you in your vacation. But this is very important to us, if you could help we will really appreciate it. I read all the examples you sent me, studied it and made several trials and errors here but something seems not to fit. There is something missing. Could you send me an example code related to our problem? So that it could enlight the path for us?

Our first valid shift is: [8..12] U [13..18]

If we could simply simulate the case in wich a task starts at 11, stops at 12 and resume at 13 would be enough for us to continue.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223#issuecomment-487929313, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3IINLVPLYH4VQSMNPLPTA2IDANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

Thank you Laurent,

Now I understand your logic. The problem is that my code have a different structure. It was based initially in this code: https://github.com/google/or-tools/blob/stable/examples/dotnet/JobshopSat.cs

So I tried to apply your logic:

[MY ORIGINAL CODE]

where odf = job and operation = task image

[AFTER TRYING TO APPLY YOUR IDEA] image

Of course my attempt is wrong, because my start is a IntVar not an NewEnumeratedIntVar. It found no solutions. But I think the answer is something like this.

When my code is working it writes to the console something like this:

Machine 5: Task O1J5M5D6 starts at 8

If starts at 8; duration = 6

I'm trying to do, following your idea, when starts at 11 for example it answers me:

Machine 5: Task O1J5M5D7 starts at 11

If starts at 11; duration = 7

Same thing, but with a different model data structure. How can I do this?

lperron commented 5 years ago

You can add start != break value if you want to the model.

You can also use AddLinearSumWithBounds() API (no need to create the tuple <start, 1>.

I do not understand your question. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le mar. 30 avr. 2019 à 20:34, gustavo-barros notifications@github.com a écrit :

Thank you Laurent,

Now I understand your logic. The problem is that my code have a different structure. It was based initially in this code:

https://github.com/google/or-tools/blob/stable/examples/dotnet/JobshopSat.cs

So I tried to apply your logic:

[MY ORIGINAL CODE]

where odf = job and operation = task [image: image] https://user-images.githubusercontent.com/36746102/56982513-e16f3800-6b57-11e9-8a23-4dc76e7f7668.png

[AFTER TRYING TO APPLY YOUR IDEA] [image: image] https://user-images.githubusercontent.com/36746102/56982540-f1871780-6b57-11e9-9048-c87a667e7908.png

Of course my attempt is wrong, because my start is a IntVar not an NewEnumeratedIntVar. It found no solutions. But I think the answer is something like this.

When my code is working it writes to the console something like this:

Machine 5: Task O1J5M5D6 starts at 8

If starts at 8; duration = 6

I'm trying to do, following your idea, when starts at 11 for example it answers me:

Machine 5: Task O1J5M5D7 starts at 11

If starts at 11; duration = 7

Same thing, but with a different model data structure. How can I do this?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223#issuecomment-488065009, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3I3NGZGPODNTPYVEE3PTCGKPANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

Hi Laurent, I noticed that you added new features in the current version:

image

In the example you showed, the duration of the task could be 4 or 3 if is crossing or not. But how can I express thousands of tasks that can be expanded like that over the intervals?

For example, I have 4 different tasks with different durations. If they cross the interval they will be added up 1 unit of time, right. For example:

tasks durations:

if task_0 start at 12 AM it will end at 16 PM, hence duration = 4 if task_1 start at 12 AM it will end at 17 PM, hence duration = 5 if task_2 start at 11 AM it will end at 18 PM, hence duration = 7 if task_3 start at 10 AM it will end at 18 PM, hence duration = 8

So in summary:

It is possible to define a range like this?

duration = model.NewIntVar(3, 8, 'duration')

meaning that duration ranges of 3 to 8? Or should I do something like this?

duration = model.NewIntVarFromDomain( cp_model.Domain.FromIntervals([(3, 4), (4, 5), (6, 7), (7, 8)]), 'duration')

Now, if I have different intervals durations? For example, imagine the lunch break is at 13 PM to 14 PM and after 18 PM is the shutdown break interval. So it will span from 18 PM to 8 AM. And if a task with duration 4 start at 17 PM it should span until 8 AM, so duration is 18. With these NewIntVarFromDomain, can I express this case also?

gustavo-barros commented 5 years ago

Hey Laurent,

See the red box, "operation.Duration" is the value I want to change depending on a BoolVar. How can I make that?

image

So I was trying to apply your example in my code in such a way I could change the operation.Duration value depending on the change of the "duration" variable, as the image show below:

image

In this case "operation.Duration" would be 4 if "across" is true.

Is this possible? How can I do that?

gustavo-barros commented 5 years ago

Something like this: image

lperron commented 5 years ago

Exactly. As a small optimization, you can write model.Add(duration == 3 + across); Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

De : gustavo-barros notifications@github.com Date : mer. 15 mai 2019 à 20:13 À : google/or-tools Cc : Laurent Perron, Mention

Something like this:

[image: image] https://user-images.githubusercontent.com/36746102/57798806-ed482600-7723-11e9-8c10-912abe031bda.png

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223?email_source=notifications&email_token=ACUPL3N2U5ORPWH4XLKQDATPVRHENA5CNFSM4HIZUSHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVPP3IA#issuecomment-492764576, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3OHNSJ3Y5QOOOWHMRTPVRHENANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

I'm just trying some random values while I'm testing, I end up with this scenario:

image

I added a property of type "IntVar" called "ComputedDuration" to the "operation" class. Added a NewIntVar called "operationDuration" and added it to a list of IntVar. My expectation is, duration will be calculed depending on cross inside the solver and stored in my "operationDuration" variable and then inside the list, that I hope I can access after the calculation. But I can't, I get something like this:

image

image

In that I just have the domain (possible values) but not the duration itself. How can I retrieve this duration value after the calculation by the solver?

lperron commented 5 years ago

If there is a variable attached, you can ask the solver the value of that variable in the solution. You just need to store that variable.

Furthermore, when creating the duration variable, please try to restrict the bounds of the variable as much as possible (prefer [3--8] instead of [0--horizon]). Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

De : gustavo-barros notifications@github.com Date : mer. 15 mai 2019 à 21:51 À : google/or-tools Cc : Laurent Perron, Mention

I'm just trying some random values while I'm testing, I end up with this

scenario:

[image: image] https://user-images.githubusercontent.com/36746102/57804108-43bb6180-7730-11e9-9ca6-65bfd9fc1d09.png

I added a property of type "IntVar" called "ComputedDuration" to the "operation" class. Added a NewIntVar called "operationDuration" and added it to a list of IntVar. My expectation is, duration will be calculed depending on cross inside the solver and stored in my "operationDuration" variable and then inside the list, that I hope I can access after the calculation. But I can't, I get something like this:

[image: image] https://user-images.githubusercontent.com/36746102/57804369-e83da380-7730-11e9-83f7-9f9e5024c00b.png

[image: image] https://user-images.githubusercontent.com/36746102/57804387-f1c70b80-7730-11e9-818a-992d09116dd0.png

In that I just have the domain (possible values) but not the duration itself. How can I retrieve this duration value after the calculation by the solver?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223?email_source=notifications&email_token=ACUPL3MRO2RFKWGJEP5543DPVRSU5A5CNFSM4HIZUSHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVPYIKQ#issuecomment-492799018, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3OW5RSGUTMXJH5LF53PVRSU5ANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

Ok Laurent, here are the major changes:

image

So I tried to ask the solver for the value here: image

is that right? check the variable names changing. Where duration00 is the duration for the job 0 and task 0, and duration30 is the duration for the job 3 and task 0. image image

That

solver.Value(var)

should return me the duration value?

here is the scenario I'm trying to do, all tasks has lenght 3. So aproximately at 02:45-03:00 it should expand to +1 in lenght. Disregard the time scale, is not configured right.

image image

gustavo-barros commented 5 years ago

I'm almost there, but something is still not right.

lperron commented 5 years ago

either

model.Add(Duration == data.duration + across)

or

model.Add(duration == data.Duration).OnlyEnforceIf(across.Not()) model.Add(duration == data.Duration + 1).OnlyEnforceIf(across)

Not a mix. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

De : gustavo-barros notifications@github.com Date : mer. 15 mai 2019 à 22:39 À : google/or-tools Cc : Laurent Perron, Mention

Ok Laurent, here are the major changes:

[image: image] https://user-images.githubusercontent.com/36746102/57807073-d19a4b00-7736-11e9-955f-9feeb24ee166.png

So I tried to ask the solver for the value here: [image: image] https://user-images.githubusercontent.com/36746102/57807184-09a18e00-7737-11e9-9419-bd09a26b74b0.png

is that right? check the variable names changing. Where duration00 is the duration for the job 0 and task 0, and duration30 is the duration for the job 3 and task 0. [image: image] https://user-images.githubusercontent.com/36746102/57807256-2fc72e00-7737-11e9-988a-546c564739ad.png [image: image] https://user-images.githubusercontent.com/36746102/57807310-4ec5c000-7737-11e9-83ec-e01daeddebde.png

That

solver.Value(var)

should return me the duration value?

here is the scenario I'm trying to do, all tasks has lenght 3. So aproximately at 02:45-03:00 it should expand to +1 in lenght. Disregard the time scale, is not configured right.

[image: image] https://user-images.githubusercontent.com/36746102/57807733-22f70a00-7738-11e9-893c-ce051fcf0dc6.png [image: image] https://user-images.githubusercontent.com/36746102/57807762-3013f900-7738-11e9-9907-a22b7413d7f7.png

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223?email_source=notifications&email_token=ACUPL3PB2DNBMGDTHNPLR63PVRYGXA5CNFSM4HIZUSHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVP4EEQ#issuecomment-492814866, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3JEZJMFEC37W4YPVEDPVRYGXANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

Yes, I already fixed that. But it still returns 3 for all the data. For the machine_1 should be some 4's.

This give me a impression that maybe something related with the intervals?

gustavo-barros commented 5 years ago

I can provide more code if needed, any ideas? Really need your help. Seems the durations values are always setted to 3, that's the same as the original data.Duration. For some reason seems it doesn't setting the across state. But I have no sure :(

gustavo-barros commented 5 years ago

Yes, made some tests here. Across state are not being activated

lperron commented 5 years ago

It was in the code I wrote. So debug your code. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

De : gustavo-barros notifications@github.com Date : mer. 15 mai 2019 à 23:54 À : google/or-tools Cc : Laurent Perron, Mention

Yes, made some tests here. Cross state are not being activated

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223?email_source=notifications&email_token=ACUPL3OTFYTH3WNVNTNJBVLPVSBCBA5CNFSM4HIZUSHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVQBZKI#issuecomment-492838057, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3KPD3MHOSH44MQU3J3PVSBCBANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

Ok. Can you explain for me how this two methods works or give me a direction where I can find reference about it?

Model.AddLinearExpressionInDomain()

Model.AddLinearConstraint()

I have sure it is something about the intervals that is not right, and then the "across" state is not becoming true.

lperron commented 5 years ago

A domain in a set of values build from values or integer intervals.

AddLinearConstraint(linear_expr, lb, ub) == AddLinearExpressionInDomain(linear_expr, new Domain(lb, ub))

The domain class is documented here:

https://github.com/google/or-tools/blob/master/ortools/util/sorted_interval_list.h#L57

Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

De : gustavo-barros notifications@github.com Date : jeu. 16 mai 2019 à 13:56 À : google/or-tools Cc : Laurent Perron, Mention

Ok. Can you explain for me how this two methods works or give me a

direction where I can find reference about it?

Model.AddLinearExpressionInDomain()

Model.AddLinearConstraint()

I have sure it is something about the intervals that is not right, and then the "across" state is not becoming true.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223?email_source=notifications&email_token=ACUPL3LYBPHYWKJRKLVW7FLPVVDWRA5CNFSM4HIZUSHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVRSLMA#issuecomment-493036976, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3JOJZYPIQCMSSYWRODPVVDWRANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

this is the AddLinearConstraint() method that we are using?

https://github.com/google/or-tools/blob/v7.0/ortools/sat/pb_constraint.h#L150

lperron commented 5 years ago

No, this is an internal propagation code dedicated to pseudo-boolean constraints (that is linear constraints with Boolean variables). Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

De : gustavo-barros notifications@github.com Date : jeu. 16 mai 2019 à 14:24 À : google/or-tools Cc : Laurent Perron, Mention

this is the AddLinearConstraint() method that we are using?

https://github.com/google/or-tools/blob/v7.0/ortools/sat/pb_constraint.h#L150

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223?email_source=notifications&email_token=ACUPL3K6S4RGCEQ7ILNAJWTPVVG7PA5CNFSM4HIZUSHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVRUNEY#issuecomment-493045395, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3JGH22WJZ2GMXISQ73PVVG7PANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

Hey Laurent, I was right about the domains, now it's working half the logic, thank you. I'm trying to adapt to my scenario, so I still have some doubts.

For example, I have this: image

But I would like something like this: image Of course I wouldn't declare the same variable twice. I need this OneTask to receive each one depending on the bool variables.

I'll explain you why I need that. Each machine has different inactive intervals during a day. So I'll try to loop over a array of NewBoolVar for each interval and a array of Durations. Something like this in the case of durations: image

I need this because if a task hit the first interval it expands 1x4 blocks (1 hour in four 15 minutes blocks), BUT if a task hit the second interval that goes from 18:00 to 08:00 next day. It should expand 14x4 blocks. So how can I set my "OneTask" variable depending on my NewBoolVars ?

Here is the image of the first functional expansion: image

lperron commented 5 years ago

Have you seen

https://github.com/google/or-tools/blob/f3fd201e68cf75b7720ff5c3cadc599a1d02b54b/examples/dotnet/GateSchedulingSat.cs#L92

? Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

De : gustavo-barros notifications@github.com Date : jeu. 16 mai 2019 à 20:03 À : google/or-tools Cc : Laurent Perron, Mention

Hey Laurent,

I was right about the domains, now it's working half the logic, thank you. I'm trying to adapt to my scenario, so I still have some doubts.

For example, I have this: [image: image] https://user-images.githubusercontent.com/36746102/57874880-f4386c80-77e7-11e9-8118-32f41d2d47ff.png

But I would like something like this: [image: image] https://user-images.githubusercontent.com/36746102/57874979-2c3faf80-77e8-11e9-9da7-843564c3f118.png Of course I wouldn't declare the same variable twice. I need this OneTask to receive each one depending on the bool variables.

I'll explain you why I need that. Each machine has different inactive intervals during a day. So I'll try to loop over a array of NewBoolVar for each interval and a array of Durations. Something like this in the case of durations: [image: image] https://user-images.githubusercontent.com/36746102/57876375-8b52f380-77eb-11e9-86a9-d0e680bc6290.png

I need this because if a task hit the first interval it expands 1x4 blocks (1 hour in four 15 minutes blocks), BUT if a task hit the second interval that goes from 18:00 to 08:00 next day. It should expand 14x4 blocks. So how can I set my "OneTask" variable depending on my NewBoolVars ?

Here is the image of the first functional expansion: [image: image] https://user-images.githubusercontent.com/36746102/57875784-17641b80-77ea-11e9-9b19-bc4ca21fde21.png

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223?email_source=notifications&email_token=ACUPL3O5N5XR4DA6RCQIFS3PVWOVRA5CNFSM4HIZUSHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVSTLTA#issuecomment-493172172, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3PFO4MRS3AW6UZ3R5TPVWOVRANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

There is a way to do set operations like, union, intersect, exclude using Domains? Would be very good if possible.

gustavo-barros commented 5 years ago

For example if we have:

var availableDomain = Domain.FromIntervals(new[]
                    {
                        new long[] {8, 12},
                        new long[] {13, 18},
                        new long[] {27, 31},
                        new long[] {32, 137}
                    });

                    var crossingDomain1 = Domain.FromIntervals(new[]
                    {
                        new long[] {11, 12}
                    });

                    var crossingDomain2 = Domain.FromIntervals(new[]
                    {
                        new long[] {16,17}
                    });

                    notCrossingDomain = availableDomain.Exclude(crossingDomain1);
                    notCrossingDomain.Exclude(crossingDomain2);

// SO WE HAVE AT END
                    notCrossingDomain =
                    {
                        {8, 10},
                        {13, 15},
                        {18, 27},
                        {32, 137}
                    }

Or something like that

lperron commented 5 years ago

It is possible in C++, I did not wrap all functions in C#. I will do it for 7.2.

Here is the API in C++

https://github.com/google/or-tools/blob/f3fd201e68cf75b7720ff5c3cadc599a1d02b54b/ortools/util/sorted_interval_list.h#L65 Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

De : gustavo-barros notifications@github.com Date : jeu. 16 mai 2019 à 21:56 À : google/or-tools Cc : Laurent Perron, Mention

For example if we have:

var availableDomain = Domain.FromIntervals(new[] { new long[] {8, 12}, new long[] {13, 18}, new long[] {27, 31}, new long[] {32, 137} });

                var crossingDomain1 = Domain.FromIntervals(new[]
                {
                    new long[] {11, 12}
                });

                var crossingDomain2 = Domain.FromIntervals(new[]
                {
                    new long[] {16,17}
                });

                notCrossingDomain = availableDomain.Exclude(crossingDomain1);
                notCrossingDomain.Exclude(crossingDomain2);

// SO WE HAVE AT END notCrossingDomain = { {8, 10}, {13, 15}, {18, 27}, {32, 137} }

Or something like that

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223?email_source=notifications&email_token=ACUPL3IAV6OSKJGN6CU4MWDPVW36VA5CNFSM4HIZUSHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVS4SIQ#issuecomment-493209890, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3PENMXUIGKA5GDFWBDPVW36VANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

Hey Laurent, I'm almost done with this feature. But I still have some problems. I'm trying to write a sequencial code that simulates a loop with 2 iterations (can be more later, if it works). So I'm doing the things in double to attempt to set these durations variations through different intervals of different lenght ( in this case 2 different intervals). For each block I calculate the crossing and non-crossing domains because it depends on the block lenght.

The first run I setted just the first interval, and it worked as you can see below:

image

image

In the second run I setted the second interval, and it also worked as you can see below:

image

image

In the third run I tryed to bring all together and setted the first and second intervals, this time things runned wild (don't know why yet) as you can see:

image

image

Any ideas?

gustavo-barros commented 5 years ago

How the domains were calculated:

image

Maybe it should not have intersections between the notCrossings?

image

lperron commented 5 years ago

I would suggest the following

write a loop for the start

accumulate the duration of the task, skip breaks, and record end and total duration

bucketize these

duration = 2 on {...} duration = 3 on {...}

use this in the Domain.FromValues() Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le ven. 17 mai 2019 à 17:05, gustavo-barros notifications@github.com a écrit :

How the domains were calculated:

[image: image] https://user-images.githubusercontent.com/36746102/57937272-f6f49980-789b-11e9-9244-716610bd224c.png

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223?email_source=notifications&email_token=ACUPL3MJRQ7C473QZEZCXRLPV3CUDA5CNFSM4HIZUSHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVVALRY#issuecomment-493487559, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3N6ZTZH42JTZ7PIBZ3PV3CUDANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

Sorry, I didn't understand how to apply what you said in my code.

gustavo-barros commented 5 years ago

Hey Laurent,

Good news! I was able to solve the problem. Expansions for different intervals lenghts. Give it a look:

image

But now I'm having a collateral problem. I don't know why the tasks are preferably being put at the right of the available intervals in all cases when its possible. It should be put preferably at left, there is no sense to let the machines idles like that.

image

image

image

Any idea?

lperron commented 5 years ago

short answer, because nobody tells the solver to do so.

long answer: solve the problem once. Store the optimal makespan. Change the model to fix the makespan and minimize the sum of start times of tasks resolve the problem. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le lun. 20 mai 2019 à 16:41, gustavo-barros notifications@github.com a écrit :

Hey Laurent,

Good news! I was able to solve the problem. Expansions for different intervals lenghts. Give it a look:

[image: image] https://user-images.githubusercontent.com/36746102/58029578-4385e200-7af3-11e9-904b-d580bc1e2ff9.png

But now I'm having a collateral problem. I don't know why the tasks are being preferably being put at the right of the available intervals in all cases when its possible. It should be put preferably at left, there is no sense to let the machines idles like that.

[image: image] https://user-images.githubusercontent.com/36746102/58029174-7380b580-7af2-11e9-9470-4a7654340126.png

[image: image] https://user-images.githubusercontent.com/36746102/58029308-a9be3500-7af2-11e9-84d2-e1818d592ec8.png

[image: image] https://user-images.githubusercontent.com/36746102/58029372-c9edf400-7af2-11e9-97e9-f670c4ab4dc2.png

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223?email_source=notifications&email_token=ACUPL3K56RGEIZUZN6B2AQTPWK2DFA5CNFSM4HIZUSHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVZBQDY#issuecomment-494016527, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3PXRHM4GBM4UTJ2NLLPWK2DFANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

Hmmm I see.

How can I do that storage procedure following a remodeling process? You have any example for me to see?

lperron commented 5 years ago

After the first Solve(), calling Minimize() again will overwrite the previous objective. Then you can add a constraint on the makespan as you built the model.

To speed the second solve(), you can hint the previous solution. But there are no API currently for that. Although the code will be small. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le lun. 20 mai 2019 à 16:50, gustavo-barros notifications@github.com a écrit :

Hmmm I see.

How can I do that storage procedure following a remodeling process? You have any example for me to see?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223?email_source=notifications&email_token=ACUPL3JUPWA3OOFL5O3GLZ3PWK3BPA5CNFSM4HIZUSHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVZCLMA#issuecomment-494020016, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3O3HAXLI36VFSGWFATPWK3BPANCNFSM4HIZUSHA .

gustavo-barros commented 5 years ago

Something like this:

image

In wich: image

Then solve it with the "allEndings": image

If solved as optimal set the allStarts as minimize objective:

image

Then solve it again?

image

gustavo-barros commented 5 years ago

You think it is possible to do something like this, without running the solver again?

image

In this case I have the domain of all available intervals. So if in some way I could tell the solver that the task start should be always bigger or equal to the start of the available interval. But preferably equal or the closest possible. Maybe then running the solver again wouldn't be necessary.

gustavo-barros commented 5 years ago

Hey Laurent,

Have you any material explaining how these works?

DecisionStrategyProto.Types.VariableSelectionStrategy DecisionStrategyProto.Types.DomainReductionStrategy

There are some options inside those classes like for example "ChooseFirst". I would like to know how each of these works, what it is for, etc.

Also you have something about these:

Model.AddMaxEquality(); Model.Minimize();

And others functions similar to those?

lperron commented 5 years ago

Everything is documented in non C# languages. C# doc tags are just too painful to use.

https://github.com/google/or-tools/blob/stable/ortools/sat/cp_model.proto

or

https://github.com/google/or-tools/blob/stable/ortools/sat/python/cp_model.py https://github.com/google/or-tools/blob/stable/ortools/sat/cp_model.proto

For the decision part, the names are quite explicit

Choose first variable, choose variable with min size... select min value...

AddMaxEquality(target, IntVar[] array) => target == max(array) Minimize(linear_expr) is the objective to minimize.

Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00

Le mar. 21 mai 2019 à 12:53, gustavo-barros notifications@github.com a écrit :

Hey Laurent,

Have you any material explaining how these works?

DecisionStrategyProto.Types.VariableSelectionStrategy DecisionStrategyProto.Types.DomainReductionStrategy

There are some options inside those classes like for example "ChooseFirst". I would like to know how each of these works, what it is for, etc.

Also you have something about these:

Model.AddMaxEquality(); Model.Minimize();

And others functions similar to those?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1223?email_source=notifications&email_token=ACUPL3KP4M5CK22YO3FT33TPWPICJA5CNFSM4HIZUSHKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODV3Q6LA#issuecomment-494341932, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3LVLIC6NAEZ2DMU5I3PWPICJANCNFSM4HIZUSHA .