Scipy Optimize非线性约束使用困惑及代码报错求助
问题解决与代码修正
错误原因分析
- 目标函数参数格式错误:
scipy.optimize.minimize要求目标函数接受一维数组作为输入,最初的f2(m,n)不符合要求,导致"missing required positional argument"错误。 - 运算语法错误:Python不支持隐式乘法,
f函数中-1/2(m**2 + ...)、1/2(n+m)这类写法会被解析为调用1/2这个数值对象,触发"'int' object is not callable"错误。 - 结果调用错误:
minimize返回的是OptimizeResult对象,直接访问.OptimizeResult是错误的,应该取.x属性获取最优解。 - 约束条件不完善:原约束仅设置了
x[1]-x[0]的范围,但未严格保证log函数的定义域(如n>m、1>n),容易出现数值错误。
修正后的完整代码
import math from scipy.optimize import minimize import numpy as np from scipy.optimize import NonlinearConstraint # 修正自由能函数:添加隐式乘法的乘号,确保语法正确 def f(m, n, a, b): return -1/2 * (m**2 + a**2 * n**2) + a**2 * n + 1/b * ( (n+m)/2 * math.log(1/2 * (n+m)) + (n-m)/2 * math.log(1/2 * (n-m)) + (1-n) * math.log(1-n) ) # 修正后的优化函数 def minimiser(f, a, b, m0, n0): # 目标函数:接受一维数组x,x[0]=m,x[1]=n def f2(x): return f(x[0], x[1], a, b) # 约束1:n > m,设置极小下限避免等于0(保证log(n-m)有意义) con1 = lambda x: x[1] - x[0] cons1 = NonlinearConstraint(con1, 1e-8, np.inf) # 约束2:1 > n,保证log(1-n)有意义 con2 = lambda x: 1 - x[1] cons2 = NonlinearConstraint(con2, 1e-8, np.inf) # 执行优化:bounds保证0 < m <1,0 < n <1,约束保证n>m且n<1 result = minimize( f2, (m0, n0), bounds=((1e-8, 1-1e-8), (1e-8, 1-1e-8)), constraints=[cons1, cons2] ) # 返回最优的m和n return result.x[0], result.x[1] # 测试示例 if __name__ == "__main__": a_val = 1.0 b_val = 2.0 m_init = 0.2 n_init = 0.5 m_opt, n_opt = minimiser(f, a_val, b_val, m_init, n_init) print(f"最优解:m={m_opt:.4f}, n={n_opt:.4f}") print(f"验证约束:0<m<n<1 → {0<m_opt<n_opt<1}")
关键修改说明
- 语法修正:在
f函数中所有数字与括号之间添加*,解决隐式乘法导致的调用错误。 - 目标函数格式:将
f2改为接受一维数组参数,符合minimize的要求。 - 约束完善:添加两个非线性约束,严格保证
n>m和1>n,同时在bounds中设置极小的上下限避免边界值触发log(0)错误。 - 结果返回:通过
result.x获取最优解的m、n值,而非错误的.OptimizeResult调用。
内容的提问来源于stack exchange,提问作者Fellon
相关产品推荐
相关产品推荐

