In the problem described below, I try to find the optimal mix of batch size and number of production runs to meet at minimum certain outcome value. While I am quite sure that for the given data constellation the problem is indeed infeasible, I want to avoid that solver returns infeasible due to "human error" ;)
Running the code below with ipopt, it gives the following feasible result:
Optimal number of batches (x): 0.9999999903937844
Optimal batch size (a): 6.363636302503406
Optimal total production: 6.3636362413729435
However, the values of variables a and x should be integer.
- How can I refine my constraints as I learned that Pyomo is not accepting constraints which return boolean?
- How can I formulate the constraint that 0.2a and 0.8a are integer? If boolean expressions were allowed, it would be something like
float(0.2*a).is_integer().
The code:
model.x = Var(name="Number of batches", domain=NonNegativeIntegers, initialize=10)
model.a = Var(name="Batch Size", domain=NonNegativeIntegers, bounds=(5,20))
# Objective function
def total_production(model):
return model.x * model.a
model.total_production = Objective(rule=total_production, sense=minimize)
# Constraints
# Minimum production of the two output products
def first_material_constraint_rule(model):
return sum(0.2 * model.a * i for i in range(1, value(model.x)+1)) >= 70
model.first_material_constraint = Constraint(rule=first_material_constraint_rule)
def second_material_constraint_rule(model):
return sum(0.8 * model.a * i for i in range(1, value(model.x)+1)) >= 90
model.second_material_constraint = Constraint(rule=second_material_constraint_rule)
# At least one production run
def min_production_rule(model):
return model.x >= 1
model.min_production = Constraint(rule=min_production_rule)
I don't have pyomo so I demonstrate with
differential_evolution. Maintaining that0.2a,0.8aandaare all integers is easy by defining the decision variable as 0.2*a, and derivingawithin the objective and constraint functions. Also, don't run asumwithin the constraint; that evaluates to x(x + 1)/2: