Gekko方程定义报错求助:无等号/不等号的方程异常
问题分析与解决方案
报错原因
你遇到的@error: Equation Definition错误,根源在于:
fitness()函数在求解前就尝试访问Gekko变量的.value属性,但此时变量尚未被求解赋值,会导致无效计算。- 函数返回的是Python数值(或
unmoeglich常量),而非Gekko可解析的符号表达式。Gekko需要基于变量的表达式来构建目标函数和约束,直接传入数值或布尔值会导致无法识别的方程定义(比如出现true这样的无效表达式)。
修改后的代码
from gekko import GEKKO def read_data(filename): # 保留你的原有实现 pass def get_min_max_boxen(sorten, kleider): # 保留你的原有实现 pass def finde_gruppen(stile_set): # 保留你的原有实现,假设返回风格集合的组合(比如子集) pass # 读取数据 sorten, stile, kombinierbar, kleider, gesamt = read_data("paeckchen0.txt") unmoeglich = gesamt + 1 min_boxen, max_boxen = get_min_max_boxen(sorten, kleider) print("Min. Anzahl Boxen: ", min_boxen) print("Max. Anzahl Boxen: ", max_boxen) # 初始化Gekko模型 m = GEKKO(remote=False) m.options.max_time = 1000 m.options.max_iter = 1000 m.options.max_memory = 1000 # 定义变量:var[i][k] = 第i个箱子中第k件衣物的数量 var = [[m.Var(lb=0, ub=min(kleid[2], 3), integer=True, name=f"{kleid[0]}_{kleid[1]}_{i}") for kleid in kleider] for i in range(max_boxen)] # --- 1. 构建目标函数:最小化剩余衣物总量 --- total_remaining = m.Var(lb=0) m.Equation(total_remaining == sum(kleid[2] - sum(var[i][k] for i in range(max_boxen)) for k, kleid in enumerate(kleider))) m.Minimize(total_remaining) # --- 2. 添加约束:衣物使用量不超过可用数量 --- for k, kleid in enumerate(kleider): total_used = sum(var[i][k] for i in range(max_boxen)) m.Equation(total_used <= kleid[2]) # --- 3. 添加约束:禁止无效风格组合 --- # 为每个箱子的每个风格定义二进制变量:b[i][s] = 1表示箱子i包含风格s,0表示不包含 style_list = list(stile) b = [[m.Var(lb=0, ub=1, integer=True, name=f"box_{i}_style_{s}") for s in style_list] for i in range(max_boxen)] # 关联二进制变量与衣物数量:如果箱子i中某风格s的衣物总量>0,则b[i][s]=1;否则=0 for i in range(max_boxen): for s_idx, s in enumerate(style_list): # 找出所有属于风格s的衣物索引 style_kleider_indices = [k for k, kleid in enumerate(kleider) if kleid[1] == s] total_in_box = sum(var[i][k] for k in style_kleider_indices) # 约束:total_in_box <= 3*b[i][s] (因为每件衣物最多放3件,所以总量>0时b必须为1) m.Equation(total_in_box <= 3 * b[i][s]) # 约束:b[i][s] <= total_in_box (总量为0时b必须为0) m.Equation(b[i][s] <= total_in_box) # 禁止不在kombinierbar中的风格组合 allowed_groups = [set(g) for g in kombinierbar] for i in range(max_boxen): # 获取箱子i的所有风格二进制变量集合 box_style_vars = {s: b[i][s_idx] for s_idx, s in enumerate(style_list)} # 生成所有可能的风格子集(或用finde_gruppen逻辑) # 这里假设finde_gruppen返回当前箱子可能的风格组合,替换为你的逻辑 possible_groups = finde_gruppen(set(style_list)) for group in possible_groups: group_set = set(group) if group_set not in allowed_groups: # 约束:该组合中的风格不能同时出现在箱子里(最多包含len(group)-1个) m.Equation(sum(box_style_vars[s] for s in group_set) <= len(group_set) - 1) # 设置求解器并求解 m.options.SOLVER = 1 try: m.solve() # 输出结果 print("求解成功!") print(f"剩余衣物总量: {total_remaining.value[0]}") for i in range(max_boxen): print(f"\n箱子{i}的内容:") for k, kleid in enumerate(kleider): count = var[i][k].value[0] if count > 0: print(f" {kleid[0]}_{kleid[1]}: {int(count)}件") except Exception as e: print(f"求解失败: {e}")
关键修改点说明
- 移除
.value访问:所有运算直接基于Gekko变量构建符号表达式,让Gekko可以自动处理优化过程中的数值计算。 - 目标函数重构:用Gekko变量和方程定义剩余衣物总量,确保目标函数是Gekko可识别的表达式。
- 显式约束定义:
- 直接为每个衣物的总使用量添加不超过可用数量的约束,替代原函数中的条件判断。
- 引入二进制变量标记箱子中的风格存在性,通过约束禁止无效的风格组合,避免返回
unmoeglich这种常量导致的方程错误。
- 变量边界修正:将衣物数量变量的
lb=1改为lb=0,因为箱子可以不包含某些衣物(原设置会强制每个箱子必须放所有衣物,不符合打包逻辑)。
内容的提问来源于stack exchange,提问作者user23772713
相关产品推荐
相关产品推荐

