Closed KungFuPandey closed 5 years ago
If you print total_size_max, it looks very suspicious to me.
Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00
Le ven. 13 sept. 2019 à 21:53, KungFuPandey notifications@github.com a écrit :
Hi,
I tried to elaborate on the Assignment with Task Sizes by adding a multi-dimensional "size" and "total_size_max" .
The solution seems to decide to allocate everything to 1 worker only despite the fact that others are available. The result when run allocates everything to worker(machine 18).
Attaching the code as a txt file here as it doesnt supports a py extension.
test6.txt https://github.com/google/or-tools/files/3611596/test6.txt
I took this from the sample example and tweaked input data according to need. Can you help resolve ?
— 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/1578?email_source=notifications&email_token=ACUPL3KL4I6FQJQ2JF43T2LQJPVUFA5CNFSM4IWTP6Z2YY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4HLKCVBA, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3PKFZIZ5VWLSYVPLETQJPVUFANCNFSM4IWTP6ZQ .
Total_size_max is now a multi-dim array to meet the need of variable sized constraint for each machine(worker). I have just divided each "cost" by the max value so that i get a worker(machine) level max limit.
Below is the output of the same :
array([[324173, 0, 0, ..., 0, 0, 0], [ 0, 0, 0, ..., 0, 0, 0], [ 0, 0, 0, ..., 0, 0, 0], ..., [ 0, 120153, 0, ..., 0, 0, 0], [ 0, 306538, 0, ..., 0, 0, 0], [ 0, 382508, 0, ..., 0, 0, 0]])
Mostly 0, that does not leave much flexibility in the assignment. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00
Le ven. 13 sept. 2019 à 22:22, KungFuPandey notifications@github.com a écrit :
Total_size_max is now a multi-dim array to meet the need of variable sized constraint for each machine(worker). I have just divided each "cost" by the max value so that i get a worker(machine) level max limit.
Below is the output of the same : array([[324173, 0, 0, ..., 0, 0, 0], [ 0, 0, 0, ..., 0, 0, 0], [ 0, 0, 0, ..., 0, 0, 0], ..., [ 0, 120153, 0, ..., 0, 0, 0], [ 0, 306538, 0, ..., 0, 0, 0], [ 0, 382508, 0, ..., 0, 0, 0]])
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1578?email_source=notifications&email_token=ACUPL3JYQ5H2XV22K55JCGLQJPZARA5CNFSM4IWTP6Z2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD6WDBGQ#issuecomment-531378330, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3PYT4JTR42XJYR5ZZLQJPZARANCNFSM4IWTP6ZQ .
i understand, but then there are possibilities where the solution should be able to allocate it correctly.
The similar code here works (having no 1s ofcourse helped it) for lesser data-set but doesnt works for larger (and sparse) dataset. IM_test6 - Copy.txt
I have no reason not to believe this is optimal.
And the solver checks all solutions, so the model must be wrong.
Please check the model carefully. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00
Le ven. 13 sept. 2019 à 22:34, KungFuPandey notifications@github.com a écrit :
i understand, but then there are possibilities where the solution should be able to allocate it correctly.
The similar code here works (having no 1s ofcourse helped it) for lesser data-set but doesnt works for larger (and sparse) dataset.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1578?email_source=notifications&email_token=ACUPL3OXN5Q2NIBCXJT4HM3QJP2MBA5CNFSM4IWTP6Z2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD6WD5GY#issuecomment-531381915, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3PIV4TTUSYQTBC6N3LQJP2MBANCNFSM4IWTP6ZQ .
alright, the reason why there are many 0s there is because i had to add in a large number(10000000) in COST where a machine cannot make a component.
is there a way to work-around this?
Make it a -1, and when you create the boolvar, if it is -1, create a constant var with value 0.
Bonus point, do not create it, and filter all you sums checking that the cost is not -1.
Le ven. 13 sept. 2019 à 22:46, KungFuPandey notifications@github.com a écrit :
alright, the reason why there are many 0s there is because i had to add in a large number(10000000) in COST where a machine cannot make a component.
is there a way to work-around this?
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1578?email_source=notifications&email_token=ACUPL3OUBMFPIHOFHBJ4JALQJP3ZHA5CNFSM4IWTP6Z2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD6WEYII#issuecomment-531385377, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3OSG5GWVWA7VVP5KTDQJP3ZHANCNFSM4IWTP6ZQ .
thanks, your approach sounds great!
so I will be replacing the entries with -1 in cost and how would the check to ignore -1s be used in the below code ?
model.Minimize(sum([np.dot(x_row,
cost_row) for (x_row, cost_row) in zip(x, costlist)]))
`
sorry i'm totally new (but eager to learn) to or-tools if this is a simple ask.
This is not a or-tools question but a numpy one, and I never use numpy.
Sorry.
Le ven. 13 sept. 2019 à 23:02, KungFuPandey notifications@github.com a écrit :
thanks, your approach sounds great!
so I will be replacing the entries with -1 in cost and how would the check to ignore -1s be used in the below code ?
model.Minimize(sum([np.dot(x_row, cost_row) for (x_row, cost_row) in zip(x, costlist)])) `
sorry i'm totally new (but eager to learn) to or-tools if this is a simple ask.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1578?email_source=notifications&email_token=ACUPL3NSVIC2GUOXDIF63WTQJP5V3A5CNFSM4IWTP6Z2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD6WF4LQ#issuecomment-531389998, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3NZEFMEZH3UB3GT55LQJP5V3ANCNFSM4IWTP6ZQ .
Here is my interpretation of the problem
""" Created on Sat Sep 14 00:52:54 2019
@author: 320048504 """
from future import print_function
from ortools.sat.python import cp_model import time import numpy as np
def main(): model = cp_model.CpModel()
start = time.time()
cost = [[
7.995722268, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7.995722268,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7.995722268, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7.995722268, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ], [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.764712938, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.64179678, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.764712938, -1, -1, -1, -1, -1, -1, -1, -1, -1 ], [ -1, -1, -1, -1, -1, -1, 26.10110138, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26.10110138, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ], [ -1, -1, -1, -1, -1, -1, 24.79202174, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27.72432227, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29.63946277, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29.4907994, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24.79202174, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27.72432227, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29.63946277, -1, -1, -1 ], [ -1, -1, -1, 6.271052178, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.271052178, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.271052178, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.271052178, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.271052178, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.271052178, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.271052178, -1, -1, -1, -1, -1, -1 ], [ 8.213437897, -1, 4.372568825, -1, -1, -1, -1, -1, -1, -1, -1, 8.213437897, -1, 4.372568825, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4.372568825, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4.372568825, -1, -1, -1, -1, -1, -1, -1, 8.213437897, -1, 4.372568825, -1, -1, -1, -1, -1, -1, -1, -1, 8.213437897, -1, 4.372568825, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4.372568825, -1, -1, -1, -1, -1, -1, -1 ], [ -1, -1, -1, 6.282863934, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.282863934, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.282863934, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.282863934, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.282863934, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.282863934, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.282863934, -1, -1, -1, -1, -1, -1 ], [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15.49746661, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ], [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14.36944353, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ], [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14.95278777, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ], [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13.33333333, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13.33333333, -1, -1, -1, -1 ], [ -1, -1, -1, 6.194286893, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.194286893, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.194286893, -1, 14.56521739, -1, -1, -1, -1, -1, -1, -1, 6.194286893, -1, 17.57157641, -1, -1, -1, -1, -1, -1, -1, 6.194286893, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.194286893, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.194286893, -1, 14.56521739, -1, -1, -1, -1 ], [ 8.076237035, -1, 4.400797794, -1, -1, -1, -1, -1, -1, -1, -1, 8.076237035, -1, 4.400797794, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4.400797794, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4.400797794, -1, -1, -1, -1, -1, -1, -1, 8.076237035, -1, 4.400797794, -1, -1, -1, -1, -1, -1, -1, -1, 8.076237035, -1, 4.400797794, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4.400797794, -1, -1, -1, -1, -1, -1, -1 ], [ 8.019304639, -1, 4.496583613, -1, -1, -1, -1, -1, -1, -1, -1, 8.019304639, -1, 4.496583613, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4.496583613, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4.496583613, -1, -1, -1, -1, -1, -1, -1, 8.019304639, -1, 4.496583613, -1, -1, -1, -1, -1, -1, -1, -1, 8.019304639, -1, 4.496583613, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4.496583613, -1, -1, -1, -1, -1, -1, -1 ], [ -1, -1, -1, -1, 3.778990587, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3.778990587, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3.778990587, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3.778990587, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3.778990587, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3.778990587, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3.778990587, -1, -1, -1, -1, -1 ], [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 11.51228733, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ], [ -1, -1, 4.492667454, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4.492667454, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4.492667454, -1, -1, -1, -1, -1, -1, -1, 11.06301248, -1, 4.492667454, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4.492667454, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4.492667454, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4.492667454, -1, -1, -1, -1, -1, -1, -1 ], [ -1, -1, -1, -1, -1, -1, -1, -1, 5.512785364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5.512785364, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5.512785364, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5.512785364, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5.512785364, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5.512785364, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5.512785364, -1 ], [ -1, -1, -1, -1, -1, -1, -1, 1.780837358, -1, 1.780837358, 1.780837358, -1, -1, -1, -1, -1, -1, -1, 1.780837358, -1, 1.780837358, -1, -1, -1, -1, -1, -1, -1, 1.780837358, -1, 1.780837358, -1, -1, -1, -1, -1, -1, -1, 1.780837358, -1, 1.780837358, -1, -1, -1, -1, -1, -1, -1, 1.780837358, -1, 1.780837358, 1.780837358, -1, -1, -1, -1, -1, -1, -1, 1.780837358, -1, 1.780837358, -1, -1, -1, -1, -1, -1, -1, 1.780837358, -1, 1.780837358 ], [ -1, -1, -1, -1, -1, 7.755011055, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7.755011055, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7.755011055, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7.755011055, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ], [ -1, -1, -1, -1, -1, -1, 25.45422456, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29.69460764, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 32.00169225, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25.45422456, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 29.69460764, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ], [ -1, -1, -1, -1, -1, -1, 28.19319991, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27.13193117, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26.59704717, -1, -1, -1, -1, -1, -1, -1, -1, -1, 28.19319991, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27.13193117, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ], [ -1, 21.5723175, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21.5723175, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21.5723175, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21.5723175, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21.5723175, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21.5723175, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21.5723175, -1, -1, -1, -1, -1, -1, -1, -1 ], [ -1, 8.455696203, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8.455696203, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8.455696203, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8.455696203, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8.455696203, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8.455696203, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8.455696203, -1, -1, -1, -1, -1, -1, -1, -1 ], [ -1, 6.776314217, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.776314217, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.776314217, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.776314217, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.776314217, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.776314217, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6.776314217, -1, -1, -1, -1, -1, -1, -1, -1 ]]
int_cost = [[int(round(x)) for x in line] for line in cost]
# demand for each component
demand = [
28, 28, 28, 28, 28, 28, 28, 28, 28, 56, 28, 30, 30, 30, 30, 30, 30,
30, 30, 30, 60, 176, 176, 176, 176, 176, 176, 176, 176, 176, 352, 194, 194, 194, 194, 194, 194, 194, 194, 194, 388, 56, 56, 56, 56, 56, 56, 56, 56, 56, 112, 56, 149, 149, 149, 149, 149, 149, 149, 149, 149, 298, 911, 911, 911, 911, 911, 911, 911, 911, 911, 1822 ]
# total available hours
available_hrs = 2592000
num_workers = len(int_cost)
num_tasks = len(int_cost[1])
print('num_workers =', num_workers, ', num_tasks =', num_tasks)
# Variables
x = [[
0 if int_cost[i][j] == -1 else model.NewIntVar(
0, demand[j], 'x[%i,%i]' % (i, j)) for j in range(num_tasks)
] for i in range(num_workers)]
# Constraints
# For each component, demand is met.
for j in range(num_tasks):
model.Add(
sum(x[i][j] for i in range(num_workers)
if int_cost[i][j] >= 0) == demand[j])
# Total worked hours for each machine is at most available_hrs.
for i in range(num_workers):
model.Add(
sum(x[i][j] * int_cost[i][j]
for j in range(num_tasks)) <= available_hrs)
# Objective: minimize worked hours.
model.Minimize(
sum(x[i][j] * int_cost[i][j] for i in range(num_workers)
for j in range(num_tasks) if int_cost[i][j] != -1))
# Solve.
solver = cp_model.CpSolver()
solver.parameters.log_search_progress = True
solver.parameters.num_search_workers = 8
status = solver.Solve(model)
# Print solution.
if status == cp_model.OPTIMAL:
print('Minimum cost = %i' % solver.ObjectiveValue())
print()
for i in range(num_workers):
for j in range(num_tasks):
qty = 0 if cost[i][j] == -1 else solver.Value(x[i][j])
if qty > 0:
print('Machine ', i, ' is assigned to produce', qty,
'of Component ', j, ' with minimum Cycle_Time = ',
cost[i][j])
print()
end = time.time()
print("Time = ", round(end - start, 4), "seconds")
if name == 'main': main()
You need to meet demand, spreading each component onto different machines, while staying below max_available_hours, and minimizing total working time
It produces the following output in 64 ms on my laptop. I hope the model is correct.
num_workers = 25 , num_tasks = 72
Parameters: log_search_progress: true num_search_workers: 8
Optimization model '':
23 in [0,28]
21 in [0,30]
24 in [0,56]
1 in [0,60]
1 in [0,112]
21 in [0,149]
17 in [0,176]
23 in [0,194]
1 in [0,298]
1 in [0,352]
1 in [0,388]
17 in [0,911]
1 in [0,1822]
*** starting model expansion at 0.00s
*** starting model presolve at 0.00s
27 affine relations were detected.
25 variable equivalence relations were detected.
rule 'linear: always true' was applied 16 times.
rule 'linear: divide by GCD' was applied 17 times.
rule 'linear: empty' was applied 4 times.
rule 'linear: fixed or dup variables' was applied 6 times.
rule 'linear: remapped using affine relations' was applied 1 time.
rule 'linear: size one' was applied 43 times.
rule 'objective: expanded objective constraint.' was applied 32 times.
rule 'presolve: iteration' was applied 1 time.
Optimization model '':
18 in [0,28]
17 in [0,30]
18 in [0,56]
17 in [0,149]
11 in [0,176]
20 in [0,194]
11 in [0,911]
*** starting Search at 0.00s with 8 workers and strategies: [ auto, lp_br, pseudo_cost, no_lp, max_lp, core, helper, rnd_lns_auto, var_lns_auto, cst_lns_auto, rins/rens_lns_auto ]
CpSolverResponse:
status: OPTIMAL
objective: 125923
best_bound: 125923
booleans: 1
conflicts: 0
branches: 1
propagations: 0
integer_propagations: 138
walltime: 0.011411
usertime: 0.011412
deterministic_time: 0.000137944
primal_integral: 0
Minimum cost = 125923
Machine 1 is assigned to produce 176 of Component 21 with minimum Cycle_Time = 6.764712938
Machine 1 is assigned to produce 194 of Component 31 with minimum Cycle_Time = 6.64179678
Machine 1 is assigned to produce 911 of Component 62 with minimum Cycle_Time = 6.764712938
Machine 3 is assigned to produce 176 of Component 27 with minimum Cycle_Time = 29.63946277
Machine 3 is assigned to produce 911 of Component 68 with minimum Cycle_Time = 29.63946277
Machine 8 is assigned to produce 194 of Component 36 with minimum Cycle_Time = 14.36944353
Machine 10 is assigned to produce 176 of Component 26 with minimum Cycle_Time = 13.33333333
Machine 10 is assigned to produce 911 of Component 67 with minimum Cycle_Time = 13.33333333
Machine 11 is assigned to produce 28 of Component 3 with minimum Cycle_Time = 6.194286893
Machine 11 is assigned to produce 30 of Component 14 with minimum Cycle_Time = 6.194286893
Machine 11 is assigned to produce 176 of Component 24 with minimum Cycle_Time = 6.194286893
Machine 11 is assigned to produce 194 of Component 34 with minimum Cycle_Time = 6.194286893
Machine 11 is assigned to produce 56 of Component 44 with minimum Cycle_Time = 6.194286893
Machine 11 is assigned to produce 149 of Component 55 with minimum Cycle_Time = 6.194286893
Machine 11 is assigned to produce 911 of Component 65 with minimum Cycle_Time = 6.194286893
Machine 13 is assigned to produce 28 of Component 0 with minimum Cycle_Time = 8.019304639
Machine 13 is assigned to produce 30 of Component 11 with minimum Cycle_Time = 8.019304639
Machine 13 is assigned to produce 56 of Component 41 with minimum Cycle_Time = 8.019304639
Machine 13 is assigned to produce 149 of Component 52 with minimum Cycle_Time = 8.019304639
Machine 14 is assigned to produce 28 of Component 4 with minimum Cycle_Time = 3.778990587
Machine 14 is assigned to produce 30 of Component 15 with minimum Cycle_Time = 3.778990587
Machine 14 is assigned to produce 176 of Component 25 with minimum Cycle_Time = 3.778990587
Machine 14 is assigned to produce 194 of Component 35 with minimum Cycle_Time = 3.778990587
Machine 14 is assigned to produce 56 of Component 45 with minimum Cycle_Time = 3.778990587
Machine 14 is assigned to produce 149 of Component 56 with minimum Cycle_Time = 3.778990587
Machine 14 is assigned to produce 911 of Component 66 with minimum Cycle_Time = 3.778990587
Machine 16 is assigned to produce 28 of Component 2 with minimum Cycle_Time = 4.492667454
Machine 16 is assigned to produce 30 of Component 13 with minimum Cycle_Time = 4.492667454
Machine 16 is assigned to produce 176 of Component 23 with minimum Cycle_Time = 4.492667454
Machine 16 is assigned to produce 194 of Component 33 with minimum Cycle_Time = 4.492667454
Machine 16 is assigned to produce 56 of Component 43 with minimum Cycle_Time = 4.492667454
Machine 16 is assigned to produce 149 of Component 54 with minimum Cycle_Time = 4.492667454
Machine 16 is assigned to produce 911 of Component 64 with minimum Cycle_Time = 4.492667454
Machine 17 is assigned to produce 28 of Component 8 with minimum Cycle_Time = 5.512785364
Machine 17 is assigned to produce 30 of Component 19 with minimum Cycle_Time = 5.512785364
Machine 17 is assigned to produce 176 of Component 29 with minimum Cycle_Time = 5.512785364
Machine 17 is assigned to produce 194 of Component 39 with minimum Cycle_Time = 5.512785364
Machine 17 is assigned to produce 56 of Component 49 with minimum Cycle_Time = 5.512785364
Machine 17 is assigned to produce 149 of Component 60 with minimum Cycle_Time = 5.512785364
Machine 17 is assigned to produce 911 of Component 70 with minimum Cycle_Time = 5.512785364
Machine 18 is assigned to produce 28 of Component 7 with minimum Cycle_Time = 1.780837358
Machine 18 is assigned to produce 56 of Component 9 with minimum Cycle_Time = 1.780837358
Machine 18 is assigned to produce 28 of Component 10 with minimum Cycle_Time = 1.780837358
Machine 18 is assigned to produce 30 of Component 18 with minimum Cycle_Time = 1.780837358
Machine 18 is assigned to produce 60 of Component 20 with minimum Cycle_Time = 1.780837358
Machine 18 is assigned to produce 176 of Component 28 with minimum Cycle_Time = 1.780837358
Machine 18 is assigned to produce 352 of Component 30 with minimum Cycle_Time = 1.780837358
Machine 18 is assigned to produce 194 of Component 38 with minimum Cycle_Time = 1.780837358
Machine 18 is assigned to produce 388 of Component 40 with minimum Cycle_Time = 1.780837358
Machine 18 is assigned to produce 56 of Component 48 with minimum Cycle_Time = 1.780837358
Machine 18 is assigned to produce 112 of Component 50 with minimum Cycle_Time = 1.780837358
Machine 18 is assigned to produce 56 of Component 51 with minimum Cycle_Time = 1.780837358
Machine 18 is assigned to produce 149 of Component 59 with minimum Cycle_Time = 1.780837358
Machine 18 is assigned to produce 298 of Component 61 with minimum Cycle_Time = 1.780837358
Machine 18 is assigned to produce 911 of Component 69 with minimum Cycle_Time = 1.780837358
Machine 18 is assigned to produce 1822 of Component 71 with minimum Cycle_Time = 1.780837358
Machine 19 is assigned to produce 28 of Component 5 with minimum Cycle_Time = 7.755011055
Machine 19 is assigned to produce 30 of Component 16 with minimum Cycle_Time = 7.755011055
Machine 19 is assigned to produce 56 of Component 46 with minimum Cycle_Time = 7.755011055
Machine 19 is assigned to produce 149 of Component 57 with minimum Cycle_Time = 7.755011055
Machine 20 is assigned to produce 28 of Component 6 with minimum Cycle_Time = 25.45422456
Machine 20 is assigned to produce 56 of Component 47 with minimum Cycle_Time = 25.45422456
Machine 21 is assigned to produce 30 of Component 17 with minimum Cycle_Time = 27.13193117
Machine 21 is assigned to produce 194 of Component 37 with minimum Cycle_Time = 26.59704717
Machine 21 is assigned to produce 149 of Component 58 with minimum Cycle_Time = 27.13193117
Machine 24 is assigned to produce 28 of Component 1 with minimum Cycle_Time = 6.776314217
Machine 24 is assigned to produce 30 of Component 12 with minimum Cycle_Time = 6.776314217
Machine 24 is assigned to produce 176 of Component 22 with minimum Cycle_Time = 6.776314217
Machine 24 is assigned to produce 194 of Component 32 with minimum Cycle_Time = 6.776314217
Machine 24 is assigned to produce 56 of Component 42 with minimum Cycle_Time = 6.776314217
Machine 24 is assigned to produce 149 of Component 53 with minimum Cycle_Time = 6.776314217
Machine 24 is assigned to produce 911 of Component 63 with minimum Cycle_Time = 6.776314217
Time = 0.0643 seconds
Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00
Le ven. 13 sept. 2019 à 23:04, Laurent Perron lperron@google.com a écrit :
This is not a or-tools question but a numpy one, and I never use numpy.
Sorry.
Le ven. 13 sept. 2019 à 23:02, KungFuPandey notifications@github.com a écrit :
thanks, your approach sounds great!
so I will be replacing the entries with -1 in cost and how would the check to ignore -1s be used in the below code ?
model.Minimize(sum([np.dot(x_row, cost_row) for (x_row, cost_row) in zip(x, costlist)])) `
sorry i'm totally new (but eager to learn) to or-tools if this is a simple ask.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1578?email_source=notifications&email_token=ACUPL3NSVIC2GUOXDIF63WTQJP5V3A5CNFSM4IWTP6Z2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD6WF4LQ#issuecomment-531389998, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3NZEFMEZH3UB3GT55LQJP5V3ANCNFSM4IWTP6ZQ .
Hi Laurent,
Thanks for the comprehensive detailing on the above, this really helps!
I wanted to know how/where do you get the details of the optimization (as mentioned in above comment where variables , riles and cpsolver details are mentioned). The information from OR output stack may help me to better understand how it optimized to a solution.
How did you reach to a conclusion of choosing 8 num_search_workers only ?
also - this one is near perfect(if not perfect already) - to take care of the scenario when the demand > availability on the BEST machine , but could be met if divided to other possible 2ndbest/3rd best.. machines. I just tried this and it works absolutely perfect. This really helps!
I see there is a minor bug in this approach , if the demand for a component is increased to a large value (lets say 324000) , and the cycle_time to produce that component is just over an integer rounded value (lets say 8.0193 ), then the total hours to make it will exceed (2598253 hrs) over the available hours (2592000). it is because we are rounding off the cost from 8.019 to 8 in order to get the optimization done.
how can we address this issue ? An example to show this is below :
# -*- coding: utf-8 -*-
from __future__ import print_function
from ortools.sat.python import cp_model
import time
import numpy as np
import pandas as pd
class fetch_data:
def __init__(self):
# set COST
self.cost = [[-1,7.995722268,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[6.764712938,-1,6.64179678,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,26.10110138,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,29.63946277,27.72432227,24.79202174,29.4907994,-1,-1],
[-1,-1,-1,-1,-1,6.271052178,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,8.213437897,-1,-1,4.372568825,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,6.282863934,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,15.49746661,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,14.36944353,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,14.95278777,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,13.33333333,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,6.194286893,-1,14.56521739,-1,17.57157641,-1,-1,-1,-1,-1,-1],
[-1,8.076237035,-1,-1,4.400797794,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,8.019304639,-1,-1,4.496583613,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,3.778990587,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,11.51228733,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,11.06301248,-1,4.492667454,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,5.512785364,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1.780837358],
[-1,-1,-1,-1,-1,-1,-1,-1,7.755011055,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,29.69460764,25.45422456,32.00169225,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,27.13193117,28.19319991,26.59704717,-1,-1],
[-1,-1,-1,21.5723175,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,8.455696203,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,6.776314217,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
]
# set DEMAND
#self.demand = [1087,500000,194,1544,1544,1544,1544,1087,263,194,1087,179,84,194,1544,3088] #263 for component-1
self.demand = [ ("a",1087), ("b",500000), ("c",194), ("d",1544), ("e",1544), ("f",1544), ("g",1544), ("h",1087), ("i",263), ("j",194), ("k",1087), ("l",179), ("m",84), ("n",194), ("o",1544), ("p",3088)]
# set AVAILABLE HOURS
#self.available_hrs = [2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000]
self.available_hrs = [ ('IMM01',2592000) , ('IMM02',2592000) , ('IMM08',2592000) , ('IMM09',2592000) , ('21',2592000) , ('31',2592000) , ('32',2592000) , ('34',2592000) , ('35',2592000) , ('38',2592000) , ('40',2592000) , ('42',2592000) , ('43',2592000) , ('44',2592000) , ('45',2592000) , ('46',2592000) , ('47',2592000) , ('49',2592000) , ('56',2592000) , ('58',2592000) , ('L06',2592000) , ('L07',2592000) , ('L12',2592000) , ('L18',2592000) , ('L33',2592000) ]
def get_data():
return fetch_data()
def IM_solution(c, d, a):
model = cp_model.CpModel()
start = time.time()
# cost = [[-1,7.995722268,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
# [6.764712938,-1,6.64179678,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
# [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,26.10110138,-1,-1,-1],
# [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,29.63946277,27.72432227,24.79202174,29.4907994,-1,-1],
# [-1,-1,-1,-1,-1,6.271052178,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
# [-1,8.213437897,-1,-1,4.372568825,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
# [-1,-1,-1,-1,-1,6.282863934,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
# [-1,-1,-1,-1,-1,-1,-1,-1,-1,15.49746661,-1,-1,-1,-1,-1,-1],
# [-1,-1,-1,-1,-1,-1,-1,-1,-1,14.36944353,-1,-1,-1,-1,-1,-1],
# [-1,-1,-1,-1,-1,-1,-1,-1,-1,14.95278777,-1,-1,-1,-1,-1,-1],
# [-1,-1,-1,-1,-1,-1,-1,13.33333333,-1,-1,-1,-1,-1,-1,-1,-1],
# [-1,-1,-1,-1,-1,6.194286893,-1,14.56521739,-1,17.57157641,-1,-1,-1,-1,-1,-1],
# [-1,8.076237035,-1,-1,4.400797794,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
# [-1,8.019304639,-1,-1,4.496583613,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
# [-1,-1,-1,-1,-1,-1,3.778990587,-1,-1,-1,-1,-1,-1,-1,-1,-1],
# [-1,-1,11.51228733,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
# [-1,-1,11.06301248,-1,4.492667454,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
# [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,5.512785364,-1],
# [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1.780837358],
# [-1,-1,-1,-1,-1,-1,-1,-1,7.755011055,-1,-1,-1,-1,-1,-1,-1],
# [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,29.69460764,25.45422456,32.00169225,-1,-1],
# [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,27.13193117,28.19319991,26.59704717,-1,-1],
# [-1,-1,-1,21.5723175,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
# [-1,-1,-1,8.455696203,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
# [-1,-1,-1,6.776314217,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
# ]
cost = c
int_cost = [[int(round(x)) for x in line] for line in cost]
# demand for each component
#demand = [1087,500000,194,1544,1544,1544,1544,1087,263,194,1087,179,84,194,1544,3088] #263 for component-1
demand = d
# total available hours
#available_hrs = [2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000,2592000]
available_hrs = a
num_workers = len(int_cost)
num_tasks = len(int_cost[1])
print('num_workers =', num_workers, ', num_tasks =', num_tasks)
# Variables
x = [[
0 if int_cost[i][j] == -1 else model.NewIntVar(
0, demand[j], 'x[%i,%i]' % (i, j)) for j in range(num_tasks)
] for i in range(num_workers)]
# Constraints
# For each component, demand is met.
for j in range(num_tasks):
model.Add(
sum(x[i][j] for i in range(num_workers)
if int_cost[i][j] >= 0) == demand[j])
# Total worked hours for each machine is at most available_hrs.
for i in range(num_workers):
model.Add(
sum(x[i][j] * int_cost[i][j]
for j in range(num_tasks)) < available_hrs[i])
# Objective: minimize worked hours.
model.Minimize(
sum(x[i][j] * int_cost[i][j] for i in range(num_workers)
for j in range(num_tasks) if int_cost[i][j] != -1))
# Solve.
solver = cp_model.CpSolver()
solver.parameters.log_search_progress = True
solver.parameters.num_search_workers = 8
status = solver.Solve(model)
# Print solution.
if status == cp_model.OPTIMAL:
print('Minimum cost = %i' % solver.ObjectiveValue())
print()
lst_res = []
for i in range(num_workers):
for j in range(num_tasks):
qty = 0 if cost[i][j] == -1 else solver.Value(x[i][j])
if qty > 0:
print('Machine ', i, ' is assigned to produce', qty,
'of Component ', j, ' with minimum Cycle_Time = ',
cost[i][j])
# add each row to a list
lst = [i,j,cost[i][j],qty]
#append each list to final list
lst_res.append(lst)
print()
end = time.time()
print("Time = ", round(end - start, 4), "seconds")
df_res = pd.DataFrame(data = lst_res , columns = ['Machine#', 'Component#' , 'Cycle_Time' , 'Demand_met'])
#print(df_res)
return df_res
if __name__ == '__main__':
data = get_data()
# get Cost
c = data.cost
# get demand
d1 = data.demand
d1_dict = dict(d1)
d = list(d1_dict.values())
df_d = pd.DataFrame( data=d1 , columns = ['Component' , 'Demand'] )
df_d.reset_index(inplace = True)
df_d = df_d.rename(columns = {"index": "Component#"})
# get available hours
a1 = data.available_hrs
a1_dict = dict(a1)
a = list(a1_dict.values())
df_a = pd.DataFrame( data=a1 , columns = ['Machine' , 'Available_hours'] )
df_a.reset_index(inplace = True)
df_a = df_a.rename(columns = {"index": "Machine#"})
#print("COST :")
#print(c)
#print("DEMAND :")
#print(d)
#print("AVAILABLE HOURS :")
#print(a)
# Call IM optimization solution
df_IMres = IM_solution(c,d,a)
#print(df_IMres)
#combine result with demand and avaiable hrs to calculate metrics
df_merged1 = pd.merge(df_IMres, df_d, how = 'left', on =['Component#'])
df_merged1 = pd.merge(df_merged1, df_a, how = 'left', on =['Machine#'])
df_merged1['Max_comp_possible'] = df_merged1.apply(lambda row: (row.Available_hours / row.Cycle_Time ), axis = 1)
df_merged1['%Demand_met'] = df_merged1.apply(lambda row: (row.Demand_met / row.Demand ), axis = 1)
df_merged1['Used_hours'] = df_merged1.apply(lambda row: (row.Cycle_Time * row.Demand_met ), axis = 1)
df_merged1['%Utilization'] = df_merged1.apply(lambda row: (row.Used_hours / row.Available_hours ), axis = 1)
#df_merge1.to_csv('temp1.csv')
print(df_merged1)
You need to be conservative when rounding the time. So ceil instead of round() I would think. Laurent Perron | Operations Research | lperron@google.com | (33) 1 42 68 53 00
Le ven. 20 sept. 2019 à 10:13, KungFuPandey notifications@github.com a écrit :
I see there is a minor bug in this approach , if the demand for a component is increased to a large value (lets say 324000) , and the cycle_time to produce that component is just over an integer rounded value (lets say 8.0193 ), then the total hours to make it will exceed (2598253 hrs) over the available hours (2592000). it is because we are rounding off the cost from 8.019 to 8 in order to get the optimization done.
how can we address this issue ?
— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/google/or-tools/issues/1578?email_source=notifications&email_token=ACUPL3NTTIFRX5LA2KD7PFDQKSA37A5CNFSM4IWTP6Z2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD7F6KLA#issuecomment-533456172, or mute the thread https://github.com/notifications/unsubscribe-auth/ACUPL3OQNBZ6KZKRNNVVJK3QKSA37ANCNFSM4IWTP6ZQ .
Hi,
I tried to elaborate on the Assignment with Task Sizes by adding a multi-dimensional "size" and "total_size_max" .
The solution seems to decide to allocate everything to 1 worker only despite the fact that others are available. The result when run allocates everything to worker(machine 18).
Sample output :
Attaching the code as a txt file here as it doesnt supports a py extension.
test6.txt
I took this from the sample example and tweaked input data according to need. Can you help resolve ?