CPSAT约束中用指数计算贷款分期报错,求解决方案
解决OR-Tools非线性约束报错问题
错误原因
你遇到的TypeError是因为OR-Tools的决策变量(adjusted_duration)无法参与幂运算这类非线性操作。OR-Tools的线性/整数规划求解器仅支持线性表达式(变量与常数的加减乘组合),不能直接处理包含变量的指数、变量作为分母的除法等非线性逻辑。
可行解决方法
由于你的adjusted_duration取值范围是1-100(非常小),可以通过预计算所有可能期限对应的月供系数,将非线性约束转换为线性约束。具体步骤如下:
1. 预计算各期限的月供系数
提前算出每个期限d对应的月供计算系数,公式和你原代码逻辑一致:
import math # 月利率 monthly_rate = 0.00049 / 12 # 预计算每个期限对应的系数:(月利率) / (1 - (1+月利率)^-期限) monthly_payment_coeff = {} for d in range(1, 101): denominator = 1 - math.pow(1 + monthly_rate, -d) monthly_payment_coeff[d] = monthly_rate / denominator
2. 用布尔变量关联期限与约束
通过布尔变量标记当前选择的期限,再为每个期限添加对应的线性约束:
# 定义布尔变量数组,每个变量对应一个期限是否被选中 is_selected_duration = {} for d in range(1, 101): is_selected_duration[d] = model.NewBoolVar(f"duration_{d}_selected") # 约束:只能选中一个期限 model.Add(sum(is_selected_duration.values()) == 1) # 关联adjusted_duration与布尔变量(确保变量值等于选中的期限) model.Add(adjusted_duration == sum(d * is_selected_duration[d] for d in range(1, 101))) # 计算薪资上限的整数值(和你原代码逻辑一致) salary_limit = int(Salary * 0.5 * scaling_factor) # 为每个期限添加月供约束 for d in range(1, 101): # 将系数缩放为整数(匹配你的scaling_factor逻辑,避免浮点精度问题) scaled_coeff = int(monthly_payment_coeff[d] * scaling_factor) # 仅当该期限被选中时,约束生效 model.Add(scaled_coeff * adjusted_amount <= salary_limit).OnlyEnforceIf(is_selected_duration[d])
方法合理性说明
因为期限的取值范围极小(仅100种可能),预计算所有情况的开销可以忽略,同时将原本的非线性表达式拆分为多个线性约束,完全符合OR-Tools求解器的要求。
内容的提问来源于stack exchange,提问作者stefano guerrieri
相关产品推荐
相关产品推荐

