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

如何在CPLEX代码中编写供应商至工厂的运费区间成本函数集合?

在CPLEX中实现阶梯式区间运费成本函数

针对你给出的分段运费规则,CPLEX提供了两种常用实现方式,下面分别说明:

方法一:使用Piecewise线性函数(推荐)

这种方式最简洁,CPLEX原生支持分段线性/常数函数,直接通过定义断点和对应成本值即可实现。

OPL代码示例

// 定义供应商到工厂的运输量变量(假设为非负整数,若为连续则用float+)
dvar int+ x in 1..2500;

// 定义运费区间断点:包含每个区间的起止点,从0开始覆盖所有范围
float breakpoints[0..16] = [
    0,1,21,22,62,63,134,135,312,313,654,655,1249,1250,1964,1965,2500
];

// 定义每个断点对应的总运费:
// - 0-1:成本0到422(x≥1时触发固定成本)
// - 1-21:保持422(固定成本区间)
// - 22-62:线性增长,对应每单位13.2美元
// - 后续区间同理,最后1965-2500保持固定5533美元
float costs[0..16] = [
    0,422,422,
    22*13.2, 62*13.2,
    63*10.8, 134*10.8,
    135*8.7, 312*8.7,
    313*7.0, 654*7.0,
    655*5.9, 1249*5.9,
    1250*3.2, 1964*3.2,
    5533,5533
];

// 定义分段运费成本函数
dexpr float transportCost = piecewise(breakpoints, costs, x);

// 目标函数示例:最小化总运费(可根据实际模型调整)
minimize transportCost;

// 其他约束条件(根据你的模型需求添加)
subject to {
    // 示例约束:运输量需满足工厂需求
    // x >= demand;
}

Java API代码示例

如果使用CPLEX Java API,同样可以构建分段线性函数:

import ilog.concert.*;
import ilog.cplex.*;

public class TransportCost {
    public static void main(String[] args) throws IloException {
        IloCplex cplex = new IloCplex();
        
        // 定义运输量变量,范围1到2500
        IloIntVar x = cplex.intVar(1, 2500, "transportQuantity");
        
        // 定义断点和对应成本值
        double[] breakpoints = {
            0,1,21,22,62,63,134,135,312,313,654,655,1249,1250,1964,1965,2500
        };
        double[] costs = {
            0,422,422,
            22*13.2, 62*13.2,
            63*10.8, 134*10.8,
            135*8.7, 312*8.7,
            313*7.0, 654*7.0,
            655*5.9, 1249*5.9,
            1250*3.2, 1964*3.2,
            5533,5533
        };
        
        // 创建分段线性成本函数
        IloPiecewiseLinear pwlCost = cplex.piecewiseLinear(x, breakpoints, costs, 0, 0);
        
        // 设置目标函数:最小化总运费
        cplex.addMinimize(pwlCost);
        
        // 添加其他约束(根据模型需求)
        // cplex.addLe(x, 2500);
        // cplex.addGe(x, 1);
        
        // 求解模型
        if (cplex.solve()) {
            System.out.println("最优运输量: " + cplex.getValue(x));
            System.out.println("最优运费: " + cplex.getValue(pwlCost));
        }
        
        cplex.end();
    }
}

方法二:使用二进制变量拆分区间(适用于不支持Piecewise的场景)

如果需要手动拆分区间,可以引入二进制变量标记运输量所在区间,再通过线性约束计算成本:

dvar int+ x in 1..2500;
// 定义8个二进制变量,标记运输量是否落在对应区间
dvar boolean y1, y2, y3, y4, y5, y6, y7, y8;
// 每个区间内的增量变量
dvar int+ z1 in 0..20;   // 1-21: z1 = x-1
dvar int+ z2 in 0..40;   // 22-62: z2 = x-22
dvar int+ z3 in 0..71;   // 63-134: z3 = x-63
dvar int+ z4 in 0..177;  // 135-312: z4 = x-135
dvar int+ z5 in 0..341;  // 313-654: z5 = x-313
dvar int+ z6 in 0..594;  // 655-1249: z6 = x-655
dvar int+ z7 in 0..714;  // 1250-1964: z7 = x-1250
dvar int+ z8 in 0..535;  // 1965-2500: z8 = x-1965

subject to {
    // 确保只有一个区间被选中
    y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8 == 1;
    
    // 运输量与区间变量的关联约束
    x == 1 + z1 + 21*(y2+y3+y4+y5+y6+y7+y8);
    x == 22 + z2 + 62*(y3+y4+y5+y6+y7+y8) - 21*y1;
    x == 63 + z3 + 134*(y4+y5+y6+y7+y8) - 62*(y1+y2);
    x == 135 + z4 + 312*(y5+y6+y7+y8) - 134*(y1+y2+y3);
    x == 313 + z5 + 654*(y6+y7+y8) - 312*(y1+y2+y3+y4);
    x == 655 + z6 + 1249*(y7+y8) - 654*(y1+y2+y3+y4+y5);
    x == 1250 + z7 + 1964*y8 - 1249*(y1+y2+y3+y4+y5+y6);
    x == 1965 + z8 - 1964*(y1+y2+y3+y4+y5+y6+y7);
    
    // 增量变量仅在对应区间被选中时生效
    z1 <= 20*y1;
    z2 <= 40*y2;
    z3 <= 71*y3;
    z4 <= 177*y4;
    z5 <= 341*y5;
    z6 <= 594*y6;
    z7 <= 714*y7;
    z8 <= 535*y8;
}

// 计算总运费
dexpr float totalCost = 
    422*y1 +
    (22*13.2 + 13.2*z2)*y2 +
    (63*10.8 + 10.8*z3)*y3 +
    (135*8.7 + 8.7*z4)*y4 +
    (313*7.0 + 7.0*z5)*y5 +
    (655*5.9 + 5.9*z6)*y6 +
    (1250*3.2 + 3.2*z7)*y7 +
    5533*y8;

minimize totalCost;

这种方法虽然可行,但变量和约束数量较多,不如Piecewise函数简洁,仅推荐在特殊场景下使用。

内容的提问来源于stack exchange,提问作者Kim Huynh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 04:35:28