You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何强制Pulp与Pyomo在所有算术运算中仅使用float32精度

如何强制Pulp与Pyomo在所有算术运算中仅使用float32精度

我明白你遇到的困扰了——Pulp和Pyomo默认都用float64(也就是Python里的原生float)来处理所有算术运算,这就导致当你需要严格按照float32精度来构建约束时,会出现模型不可行或者弹出警告的情况,就像你示例里展示的那样:用float32的目标值时求解失败,但换成float64的目标就能正常得到最优解。

这是因为哪怕你传入float32类型的数值,这两个库在内部运算时还是会自动把数值提升到float64,最终的约束计算逻辑和你预期的单精度结果不匹配。下面我给你分别针对Pulp和Pyomo给出实用的解决方法:

Pulp 处理方案

Pulp没有直接设置全局精度类型的开关,但我们可以通过显式转换所有输入值为float32,同时调整求解器的精度容忍度来适配单精度的误差范围,以此对齐float32的运算逻辑。

修改你的pulp_example函数如下:

import pulp
import numpy as np

def pulp_example(values, target_float):
    # 把输入值和目标值都转换为float32类型
    float32_values = np.array(values, dtype=np.float32)
    float32_target = np.float32(target_float)
    
    variables = pulp.LpVariable.dicts("x", range(len(values)), 0, 1, pulp.LpBinary)
    problem = pulp.LpProblem("Problem", pulp.LpMinimize)
    problem += 0
    problem += pulp.lpSum([variables[i] for i in range(len(values))]) == 2
    # 构建求和表达式时使用转换后的float32数值
    sum_exp = pulp.lpSum([variables[i] * float32_values[i] for i in range(len(values))])
    # 约束条件使用float32目标值
    problem += sum_exp == float32_target
    # 调整求解器的相对间隙容忍度,适配float32的精度误差
    problem.solve(pulp.PULP_CBC_CMD(gapRel=1e-6))
    return pulp.LpStatus[problem.status]

Pyomo 处理方案

Pyomo同样默认依赖float64,但我们可以在构建模型时强制使用float32数值,同时给求解器设置合适的可行性容忍度,让求解器接受单精度范围内的误差。

修改你的pyomo_example函数如下:

import pyomo.environ as pyo
import numpy as np

def pyomo_example(values, target_float):
    float32_values = np.array(values, dtype=np.float32)
    float32_target = np.float32(target_float)
    
    model = pyo.ConcreteModel()
    model.I = pyo.RangeSet(0, len(values) - 1)
    model.x = pyo.Var(model.I, within=pyo.Binary)
    model.selection_constraint = pyo.Constraint(expr=sum(model.x[i] for i in model.I) == 2)

    def sum_expr_rule(model):
        # 每一项运算都基于float32数值
        return sum(model.x[i] * float32_values[i] for i in model.I)
    model.eq_expr = pyo.Expression(rule=sum_expr_rule)
    # 约束使用float32目标值
    model.constraint = pyo.Constraint(expr=model.eq_expr == float32_target)
    model.objective = pyo.Objective(expr=0, sense=pyo.minimize)
    
    solver = pyo.SolverFactory('cbc')
    # 设置求解器的可行性容忍度,匹配float32的精度范围
    solver.options['feasibilitytolerance'] = 1e-6
    result = solver.solve(model, tee=False)
    return result.solver.status

测试验证

使用你原来的测试代码验证修改后的效果,现在无论是float32还是float64目标值,都应该能得到预期的求解结果:

input_values = [90.2743351459503174, 4.8144315292034]

float32_target = 95.0887680053711  # float32算术结果
float64_target = 95.08876667515372  # float64算术结果
assert np.sum([input_values], dtype=np.float32) == float32_target
assert np.sum([input_values], dtype=np.float64) == float64_target

# 现在float32目标也能正常求解
pulp_res = pulp_example(input_values, float32_target)  # 返回'Optimal'
pyomo_res = pyomo_example(input_values, float32_target)  # 返回'ok'

# float64目标依然正常工作
pulp_res = pulp_example(input_values, float64_target)  # 返回'Optimal'
pyomo_res = pyomo_example(input_values, float64_target)  # 返回'ok'

额外说明

需要注意的是,大多数求解器(比如CBC)内部本身还是用双精度计算,但通过我们的转换和容忍度调整,可以让模型的行为完全符合float32算术的预期。如果需要极端严格的单精度运算,可能需要寻找支持float32的专用求解器,但对于大多数场景来说,上面的方案已经足够实用。

备注:内容来源于stack exchange,提问作者FreeDom Sy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 12:05:29