Pyomo: Comment inclure une pénalité dans la fonction objective

0

La question

J'essaie de minimiser le coût de fabrication d'un produit avec deux machines. Le coût de la machine est de 30 $/produit et le coût de la machine B est de 40 $/produit.

Il y a deux contraintes:

  • nous devons couvrir une demande de 50 produits par mois (x+y >= 50)
  • le bas prix de la machine (Un) ne peut les fabriquer 40 produits par mois (x<=40)

J'ai donc créé le Pyomo code:

from pyomo.environ import *
model = ConcreteModel()
model.x = Var(domain=NonNegativeReals)
model.y = Var(domain=NonNegativeReals)

def production_cost(m):
    return 30*m.x + 40*m.y

# Objective
model.mycost = Objective(expr = production_cost, sense=minimize)

# Constraints
model.demand = Constraint(expr = model.x + model.y >= 50)
model.maxA = Constraint(expr = model.x <= 40)

# Let's solve it
results = SolverFactory('glpk').solve(model)

# Display the solution
print('Cost=', model.mycost())
print('x=', model.x())
print('y=', model.y())

Cela fonctionne bien, avec la solution évidente x=40;y=10 (Coût = 1600)

Cependant, si on commence à utiliser la machine B, il y aura une pénalité forfaitaire de 300 $sur le coût.

J'ai essayé avec

def production_cost(m):
  if (m.y > 0):
    return 30*m.x + 40*m.y + 300
  else:
    return 30*m.x + 40*m.y

Mais je reçois le message d'erreur suivant

Rule failed when generating expression for Objective mycost with index
    None: PyomoException: Cannot convert non-constant Pyomo expression (0  <
    y) to bool. This error is usually caused by using a Var, unit, or mutable
    Param in a Boolean context such as an "if" statement, or when checking
    container membership or equality. For example,
        >>> m.x = Var() >>> if m.x >= 1: ...     pass
    and
        >>> m.y = Var() >>> if m.y in [m.x, m.y]: ...     pass
    would both cause this exception.

Je ne sais pas comment mettre en œuvre la condition pour y inclure la pénalité dans la fonction objectif par le biais de la Pyomo code.

optimization pyomo python
2021-11-22 12:46:07
1

La meilleure réponse

1

Depuis m.y est un Varvous ne pouvez pas utiliser la if déclaration avec elle. Vous pouvez toujours utiliser une variable binaire à l'aide de la Big M approche Airsquid dit-il. Cette approche est généralement pas recommandée, car elle transforme le problème de LP en MILP, mais c'est efficace.

Vous avez juste besoin de créer un nouveau Binary Var:

model.bin_y = Var(domain=Binary)

Alors contrainte model.y pour être égale à zéro si model.bin_y est égal à zéro, ou bien, être n'importe quelle valeur entre ses limites. J'utilise une borne de 100 ici, mais vous pouvez même l'utiliser à la demande:

model.bin_y_cons = Constraint(expr= model.y <= model.bin_y*100)   

puis, dans votre objectif, il suffit d'appliquer la nouvelle valeur fixe de 300:

def production_cost(m):
    return 30*m.x + 40*m.y + 300*model.bin_y 

model.mycost = Objective(rule=production_cost, sense=minimize)
2021-11-22 15:22:41

Merci @pybegginer, très bien expliqué :-) je vais aller plus loin dans l'utilisation de Big M.
Hookstark

Pour illimitée Vars vous avez besoin d'utiliser une très grande valeur de limite, comme 1E6. Dans ce genre de problème, vous aurez besoin de vérifier le solveur de tolérance Binaire, car il arrive que bin_y env. zéro, mais y est toujours supérieur à zéro: par exemple, si les limites sont fixées comme 1E6 et le binaire tolérance 1E-6, bin_y est attribué à 1E-7(très proche de zéro) mais la contrainte est y<=5 permettant à Y être plus grand que zéro. De toute façon, il suffit de double vérifier ces valeurs lorsque le modèle est résolu
pybegginer

Dans d'autres langues

Cette page est dans d'autres langues

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................