简体   繁体   English

Pyomo建模语言中的错误评估约束

[英]Error evaluating constraint in Pyomo Modelling Language

Hello to the community, 社区大家好,

So I have the following error: 所以我有以下错误:

Error evaluating constraint 5965: can't evaluate sqrt'(0). 错误评估约束5965:无法评估sqrt'(0)。 ERROR:pyomo.opt:Solver (asl) returned non-zero return code (1) ERROR:pyomo.opt:See the solver log above for diagnostic information. ERROR:pyomo.opt:Solver(asl)返回了非零返回码(1)ERROR:pyomo.opt:请参阅上面的求解器日志以获取诊断信息。

Solver (asl) did not exit normally 规划求解(ASL)不能正常退出

Actually the problem is in the following part of code: 实际上问题出在以下代码部分:

def thermal_lim_ineq_con(model, i, j, k):
    if line_loading_limit == True:
        P_branch_ij = (model.V_magn[i, k]**2) * np.float(real(Y_matrix[i, j])) - model.V_magn[i, k] * model.V_magn[j, k] * (np.float(real(Y_matrix[i, j])) * cos(model.V_angle[i, k]-model.V_angle[j, k]) + np.float(imag(Y_matrix[i,j])) * sin(model.V_angle[i, k]-model.V_angle[j, k]))
        Q_branch_ij = (model.V_magn[i, k]**2) * np.float(imag(Y_matrix[i, j])) + model.V_magn[i, k] * model.V_magn[j, k] * (np.float((real(Y_matrix[i, j]))) * sin(model.V_angle[i, k]-model.V_angle[j, k]) - np.float(imag(Y_matrix[i,j])) * cos(model.V_angle[i, k]-model.V_angle[j, k]))
        return (sqrt((P_branch_ij**2) + (Q_branch_ij**2)) <= limits_flows[i, j]) ########### ATTENTION
    else: 
        return Constraint.Skip 

model.therlim_ineq_con = Constraint(branch_from_to, scenario_set, rule = thermal_lim_ineq_con) # run this constraint for all branches 

Any ideas?? 有任何想法吗?? Removing the sqrt and squaring the variable limits_flows on the right, solves this problem but then the limits are very low ( order -6, -7) and the problem gets infeasible. 删除sqrt并对右边的变量limits_flows进行平方可解决此问题,但是限制非常低(-6,-7阶),因此该问题变得不可行。

Thank you. 谢谢。

Edit: 编辑:

Finally the problem could be solved, by giving random initial conditions to 最终,可以通过给随机的初始条件来解决该问题。

model.V_magn[i, k]

This is technically not a problem with Pyomo – but rather a problem with your formulation. 从技术上讲,这不是Pyomo的问题,而是您的配方问题。

The error is being tossed by the ASL (part of the solver executable) when the solver drives the values of P_branch_ij and Q_branch_ij to 0 (this may be happening because of an inactive line, or bad initial values). 当求解器将P_branch_ij和Q_branch_ij的值驱动为0时,该错误将被ASL(求解器可执行文件的一部分)抛出(这可能是由于无效的行或错误的初始值而发生)。 At zero, the derivative of sqrt(0) is undefined. 零时, sqrt(0)的导数未定义。 This numerical error causes the solver to exit without returning a solution. 此数值错误导致求解器退出而不返回解决方案。

There are several possible workarounds: 有几种可能的解决方法:

  1. As you pointed out in your edit, you can try different initial variable values. 正如您在编辑中指出的那样,您可以尝试不同的初始变量值。 When the solver starts from a different starting point, it may not take a path that drives P_branch_ij and Q_branch_ij to zero. 当求解器从另一个起点开始时,它可能不会采用将P_branch_ijQ_branch_ij驱动为零的路径。 The downside of this approach is that you may have to try many different initial values before getting one that does not have the solver pass through sqrt(0) , and you are not guaranteed to find one that works (especially if the solution to the problem really is at 0!). 这种方法的缺点是,您可能必须先尝试许多不同的初始值,然后才能将没有求解器的值传递给sqrt(0) ,并且不能保证找到一个有效的值(尤其是对于问题的解决方案)确实为0!)。

  2. Bound the variables so that the total branch power ( P_branch_ij**2 + Q_branch_ij**2 ) never hits zero. 绑定变量,以便总支路功率( P_branch_ij**2 + Q_branch_ij**2 )永远不会为零。 This is a bit trickier, as you cannot do it with a simple constraint: most solvers are allowed to violate constraints during the solution process and the fatal error is if the solver ever attempts to evaluate the derivative of sqrt(0) . 这有点棘手,因为您不能使用简单的约束来做到这一点:大多数求解器都可以在求解过程中违反约束,而致命的错误是如果求解器尝试评估sqrt(0)的导数。 Fortunately, most solvers will always respect variable bounds . 幸运的是,大多数求解器将始终尊重变量边界 Therefore, to prevent the solver from ever evaluating sqrt'(0) you would need to define intermediate Pyomo variables (not just Python expressions) for PQ2_branch_ij , and then set the variable lower bound to something greater than 0. The downside of this approach is you are now solving a different problem, and may force yourself to a suboptimal solution if the solution to the original problem really was at 0. 因此,为了防止从不断评估求解sqrt'(0)你将需要为定义的中间变量Pyomo(不仅仅是Python表达式) PQ2_branch_ij ,然后设置变量下限为大于0的这种方法的缺点是更大您现在正在解决另一个问题,并且如果原始问题的解决方案确实为0,则可能会迫使自己获得次优解决方案。

model.PQ2_branch_ij = Var(branch_from_to, scenario_set, bounds=(1e-8, None))
def compute_PQ2_branch_ij(m, i, j, k):
    P_branch_ij = (m.V_magn[i, k]**2) * np.float(real(Y_matrix[i, j])) - m.V_magn[i, k] * m.V_magn[j, k] * (np.float(real(Y_matrix[i, j])) * cos(m.V_angle[i, k]-m.V_angle[j, k]) + np.float(imag(Y_matrix[i,j])) * sin(m.V_angle[i, k]-m.V_angle[j, k]))
    Q_branch_ij = (m.V_magn[i, k]**2) * np.float(imag(Y_matrix[i, j])) + m.V_magn[i, k] * m.V_magn[j, k] * (np.float((real(Y_matrix[i, j]))) * sin(m.V_angle[i, k]-m.V_angle[j, k]) - np.float(imag(Y_matrix[i,j])) * cos(m.V_angle[i, k]-m.V_angle[j, k]))
    return m.PQ2_branch_ij[i,j,k] == P_branch_ij**2 + Q_branch_ij**2
def thermal_lim_ineq_con(m, i, j, k):
    return sqrt(m.PQ2_branch_ij) <= limits_flows[i, j]
if line_loading_limit:
    model.compute_PQ2_branch_ij = Constraint(branch_from_to, scenario_set, rule=compute_PQ2_branch_ij)
    model.thermal_lim_ineq_con = Constraint(branch_from_to, scenario_set, rule=thermal_lim_ineq_con)`
  1. Remove the sqrt() from the formulation by squaring limits_flows[i,j] . 通过平方limits_flows[i,j]从公式中删除sqrt() This is usually the best option: your problem is mathematically equivalent, but no longer contains the sqrt() function and will not have the problem if the branch flow goes to 0. The infeasibility that you observed when you tried this approach may be a separate issue entirely. 通常,这是最佳选择:您的问题在数学上是等效的,但不再包含sqrt()函数,并且如果分支流变为0,就不会有问题。尝试此方法时观察到的不可行性可能是单独的完全发行。 For example, with nonconvex problems (like the ACOPF) you can initialize the solver in such a way that it cannot move to a feasible position and will "converge to a point of local infeasibility" (for more explanation, see your specific solver's documentation; eg IPOPT , Knitro ). 例如,对于非凸问题(例如ACOPF),您可以通过以下方式初始化求解器:它不能移动到可行位置,并且会“收敛到局部不可行点”(有关更多说明,请参见您特定的求解器文档;例如IPOPTKnitro )。
def thermal_lim_ineq_con(model, i, j, k):
    if line_loading_limit == True:
        P_branch_ij = (model.V_magn[i, k]**2) * np.float(real(Y_matrix[i, j])) - model.V_magn[i, k] * model.V_magn[j, k] * (np.float(real(Y_matrix[i, j])) * cos(model.V_angle[i, k]-model.V_angle[j, k]) + np.float(imag(Y_matrix[i,j])) * sin(model.V_angle[i, k]-model.V_angle[j, k]))
        Q_branch_ij = (model.V_magn[i, k]**2) * np.float(imag(Y_matrix[i, j])) + model.V_magn[i, k] * model.V_magn[j, k] * (np.float((real(Y_matrix[i, j]))) * sin(model.V_angle[i, k]-model.V_angle[j, k]) - np.float(imag(Y_matrix[i,j])) * cos(model.V_angle[i, k]-model.V_angle[j, k]))
        return P_branch_ij**2 + Q_branch_ij**2 <= limits_flows[i, j]**2
    else: 
        return Constraint.Skip 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM