2
$\begingroup$

Problem: There is an order to fabricate some products of total number, let's say 200 (all products are the same). We have some number of factories, let's say 5. Every factory has different number of production lines (every line performs differently (speed of production). One of main constraints is that all factories must finish together at the same time (there is an epsilon for some small deviation).

### [Factory ID, Number Of Lines, Performance(Products per line per month)]
factories = {
['f1', 10, 2],
['f2',  3, 5],
['f3',  4, 10],
['f4',  8, 11],
['f5', 11, 17]}

order_to_fabricate = 200 # (products)


for factory in factories:
    is_factory_enabled = model.NewBoolVar(f'{factory[0]}')
    lines_per_factory_enabled = model.NewIntVar(0, factory[1], f"line per factory: {factory[0]}")
    products_per_factory = model.NewIntVar(0, order_to_fabricate, f"products per factory: {factory[0]}")
    
    model.Add(products_per_factory >= lines_per_factory_enabled)
    
    total_fab_rate = model.NewIntVar(0, factory[1]*factory[2], f"Production rate per factory: {factory[0]}") #upper bound than can be produced by factory
    model.AddMultiplicationEquality(total_fab_rate, [lines_per_factory_enabled, factory[2]])

    fabrication_duration = model.NewIntVar(0, int(round(order_to_fabricate / factory[2])), f"Production duration") #upper bound set like single line will serve total number of products
    model.AddDivisionEquality(fabrication_duration, products_per_factory, total_fab_rate) # total_fab_rate can be zero :(
    
    factory_enabled.append(is_factory_enabled)
    number_of_lines.append(lines_per_factory_enabled)
    number_of_products.append(products_per_factory)
    factory_er_for_all_lines.append(total_fab_rate)
    factory_er_duration.append(fabrication_duration)
    
# some constraints here...

The thing is that when the factory is not enabled number of lines is zero and fabricated number of products is also zero. AddDivisionEquality gets ZERO in the denominator and this constraint doesn't have the OnlyEnforceIf option.

I'm really stuck on how to avoid this issue. I want the model to select specific factories (also with some other constraints), but not all of them which is why I have is_factory_enabled.

Is there any approach to overcome such an issue?

$\endgroup$
3
  • $\begingroup$ Where does your "… all factories must finish together at the same time" come from, please? What special characteristic will cause the products to fail or spoil if any of the factories finishes early? $\endgroup$ May 19 at 23:17
  • $\begingroup$ @RobbieGoodwin it's really hard to explain the business context, but factories are going to perform specific procedures after the first stage of production and it has to be done after all products are finished. And if the factory is just waiting it wastes money. $\endgroup$
    – Shkvarka
    May 20 at 5:27
  • $\begingroup$ It might not matter at all, and there do seem to be three things in there. The time-line is one thing, the difference between "products" that really are "finished" and "components" or "assemblies" requiring further procedures is quite another. Particularly in the range of 200 items in each, or 200 spread across five factories, having items "just waiting" need not cost money, and might well save it. That still might not matter, and Laurent Perron's Answer should still solve the actual Question. $\endgroup$ May 20 at 13:02
5
$\begingroup$

I assume fab_rate is variable, otherwise you can just test it.

You can use temporary variables:

non_zero_fab_rate = model.NewIntVar(1, ..)
fab_rate_is_zero = model.NewBoolVar(..)
model.Add(non_zero_fab_rate == 1).OnlyEnforceIf(fab_rate_is_zero)
model.Add(non_zero_fab_rate == fab_rate).OnlyEnforceIf(fab_rate_is_zero.Not())
model.Add(fab_rate == 0).OnlyEnforceIf(fab_rate_is_zero)
model.Add(fab_rate > 0).OnlyEnforceIf(fab_rate_is_zero.Not())

then use the division with the non_zero_fab_rate variable, and only use the target variable if fab_rate_is_zero is false.

$\endgroup$
1
  • $\begingroup$ Thank you very much! It did solve my problem! And it took some time for me to understand how this trick works!:) $\endgroup$
    – Shkvarka
    May 21 at 9:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.