2017-06-16 2 views
0

Je souhaite créer une fonction qui renvoie une valeur par défaut (= 0) chaque fois que j'essaie d'accéder à une variable indexée avec un index non valide. C'est ce que j'ai jusqu'ici.Fonction Pyomo qui renvoie une valeur par défaut lorsqu'une erreur d'index se produit

def SafeguardIdx(object, index_set): 
    print("Guarded {} with index {}".format(object.name, index_set), index_set in object.index_set()) 
    return base.expr.Expr_if(IF=index_set in object.index_set(), THEN=object[index_set], ELSE=0) 

C'est ce que je veux:

Guarded ENDINVW_jwt with index (1, 1, 0) False 
KeyError: "Error accessing indexed component: Index '(1, 1, 0)' is not valid for array component 'ENDINVW_jwt'" 

Pourquoi accéder à l'index, même si le "IF =" est évaluée comme False?

EDIT: Je voudrais aussi vous demander si ma mise en œuvre d'une fonction min() est correcte:

def PyomoMin(a, b): 
    return base.expr.Expr_if(IF=(a > b), THEN=(a), ELSE=(b)) 

Merci à l'avance!

Répondre

2

Ce que vous voulez n'a pas vraiment de sens. La construction Expr_if ajoute un noeud à 3 arguments dans le graphe d'expression. Autrement dit, pour définir l'expression, les clauses IF, THEN et ELSE doivent toutes être des expressions Pyomo valides. Si l'expression peut être évaluée lorsque vous générez le modèle (par exemple, un index n'existe pas), vous ne devez pas utiliser Expr_if. Le SafeguardIdx peut être implémenté avec un simple python if.

En ce qui concerne la mise en œuvre min(), votre implémentation

def PyomoMin(a, b): 
    return base.expr.Expr_if(IF=(a > b), THEN=(a), ELSE=(b)) 

implémente un fait max(). Si vous voulez min(), vous devez inverser la comparaison ou spécifier THEN=b, ELSE=a. Cela dit, ce n'est généralement pas la façon recommandée d'implémenter un min(). Il y a plusieurs problèmes avec cette formulation (voir aussi Constraints involving max in a linear program?):

  1. Expr_if est uniquement disponible via l'interface NL (vous ne pouvez donc pas envoyer aux solveurs LP/MIP).
  2. min() n'est pas lisse (que la plupart des solveurs NL ont besoin), de sorte que le solveur NL peut avoir des problèmes de convergence (surtout si la solution est proche où a == b)

Il existe des alternatives à la formulation de la min, mais ils ont tous impliquer l'ajout de variables/contraintes supplémentaires et le «meilleur» dépend du reste de votre modèle. Le plus simple est d'introduire une variable supplémentaire (par exemple, minab) et de la contraindre à être inférieure à a et b. Si la pression objective essaie de maximiser minab, alors vous êtes OK. Cependant, si l'objectif veut minimiser minab, alors votre problème pourrait devenir illimité ou retourner une réponse absurde. Dans ce cas, vous devrez également implémenter la contrainte minab >= min(a,b), ce qui est délicat. Pour MIPS, une solution commune est d'introduire une variable binaire et relâcher les contraintes, par exemple:

minab >= a - M*y 
minab >= b - M*(1-y) 

Pour les modèles non linéaires vous voulez fréquemment pour éviter l'introduction de binaires si votre modèle ne possède pas déjà. Il y a des options qui peuvent passer par des choses comme des contraintes de complimentarité ou par des approximations lisses de abs().

0

J'ai trouvé une solution de travail pour le message original.

def SafeIdx(item, *index_set, default=0): 
    return item[index_set] if index_set in item.index_set() else default