Python无初始猜测求解CO2减排指数非线性方程的方案咨询
问题描述
你需要计算以下形式的指数函数作为CO₂排放减排函数:f(x) = a*exp(-b*x)+c
需满足三个约束条件:
f(x=0) = 700 Mt,对应德国当前CO₂排放量f(x=30) = 0 Mt,对应30年后实现CO₂零排放- 0到30区间内f(x)的积分等于剩余碳预算(即曲线下面积)
现有问题
原Matlab环境中调用solve函数可正常求解,迁移到Python后测试的求解器均运行失败:只有导入Matlab脚本得到的解作为初始猜测值时才能正常运行。已测试scipy的fsolve和gekko均未达到预期,希望找到无需提前提供优质初始猜测值即可正常运行的Python求解方案。
你当前使用的gekko测试代码如下:
def solve(self, end_year, budget): self.end_year = end_year self.budget = budget d_year = self.end_year - self.start_year m = GEKKO() a,b,c = [m.Var(1) for i in range(3)] eq1 = a + c - self.co2_start eq2 = a*m.exp(-b*d_year) + c eq3 = a/b*(1-m.exp(-b*d_year))+c*d_year-self.budget m.Equation([eq1==0, eq2==0, eq3==0]) m.solve(disp=False) self.a, self.b, self.c = a.value, b.value, c.value
解决方法
不需要用多变量求解器,先通过前两个约束做代数消元,把三个未知参数转化为仅关于b的单变量方程,用单变量求根方法完全不需要提前设置优质初始值:
- 从约束1推导得:
c = 700 - a - 代入约束2推导得:
a = 700 / (1 - exp(-30b)),c = -700 * exp(-30b) / (1 - exp(-30b)) - 将a、c用b表示后代入积分约束,仅需对b做单变量求根即可
可直接使用的实现代码如下:
import numpy as np from scipy.optimize import root_scalar def solve_co2_params(co2_start=700, end_year=30, budget): def residual(b): # 避免b趋近于0时的计算错误 if b <= 1e-6: return 1e10 exp_term = np.exp(-b * end_year) a = co2_start / (1 - exp_term) c = co2_start - a # 计算积分和预算的残差 integral = a / b * (1 - exp_term) + c * end_year return integral - budget # 给定足够宽的b的取值区间即可,常规减排场景下b在0.001~1范围内 sol = root_scalar(residual, bracket=[0.001, 1], method='brentq') b = sol.root exp_term = np.exp(-b * end_year) a = co2_start / (1 - exp_term) c = co2_start - a return a, b, c
brentq方法只要给定的区间两端残差符号相反就一定能收敛到根,完全不需要提前获知近似解作为初始值。
内容的提问来源于stack exchange,提问作者cedi123
相关产品推荐
相关产品推荐

