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

分支定界法求解整数线性规划的变量选择与跨平台求解器问题

分支定界求解整数线性规划的问题与疑问

一、变量选择的核心困境

我用分支定界法求解整数线性规划问题,先计算松弛问题最优解,得到变量值:

x1: 84.949144123197641
x2: 80.6791757549221
x3: 0
x4: 38.459016105691269

目标函数为最大化:

Z = 0.236x1 + 0.485x2 + 0.679x3 + 0.863x4

已知OR-Tools给出的最终最优解是:

x1: 84
x2: 144
x3: 8
x4: 66

常规分支定界会选择变量添加整数约束分支,但这里遇到问题:选哪个变量分支才能找到最优解?

我最初选了小数部分最大的x1(84.949...),分支约束为:

左节点: x1 <= 84
右节点: x1 >= 85

但后续计算无法找到更优解,算法提前终止于非最优解。但调整初始松弛问题中x1、x2的顺序后,得到不同松弛解,此时按最大小数部分选变量分支,最终能找到最优解。

请问是否存在优化的变量选择算法,能引导求解过程趋近并找到最优解?初始松弛问题的变量顺序会影响求解方向和结果,这让我困惑。

另外,我需要一款能在iOS上运行的原生C#求解器:Google-OR-Tools无法适配iOS;MathNet.Numerics不确定是否支持iOS,也不清楚如何用它求解混合整数规划(MIP)问题。

二、补充:TwoPhaseSimplexSolver求解异常问题

我在分支定界中使用TwoPhaseSimplexSolver,针对以下数组求解得到非最优解:

double[,] A = {
    {  0.09,  0.31,  0.21,  0.841 },
    { 0.069,  0.17,  0.02,  0.011 },
    {  0.52, 0.005, 0.006,  0.011 },
    {    -1,     0,     0,      0 },
    {     1,     0,     0,      0 },
    {     0,    -1,     0,      0 },
    {     0,     1,     0,      0 },
    {     0,     0,    -1,      0 },
    {     0,     0,     1,      0 },
    {     0,     0,     0,     -1 },
    {     0,     0,     0,      1 },
    {-0.679,-0.485,-0.236,-0.863 },
    { 0.679, 0.485, 0.236, 0.863 },
    {    -1,     0,     0,      0 }
};

double[] b = { 65, 20, 45, -60, 120, 0, 100, 0, 150, -1, 100, 0, 130, -85 };

double[] c = { 0.679, 0.485, 0.236, 0.863 };

但将等价约束输入在线两阶段单纯形求解器时,能得到最优解:x1=85, x2=80.8182, x3=0, x4=35.9917,约束内容如下:

max z = 0.679x1 + 0.485x2 + 0.236x3 + 0.863x4 
subject to
0.09x1 + 0.31x2 + 0.21x3 + 0.841x4 <= 65
0.069x1 + 0.17x2 + 0.02x3 + 0.011x4 <= 20
0.52x1 + 0.005x2 + 0.006x3 + 0.011x4 <= 45
x1 >= 60
x1 <= 120
x2 >= 0
x2 <= 100
x3 >= 0
x3 <= 150
x4 >= 1
x4 <= 100
0.679x1 + 0.485x2 + 0.236x3 + 0.863x4 >= 0
0.679x1 + 0.485x2 + 0.236x3 + 0.863x4 <= 130
x1 >= 85
and x1,x2,x3,x4 >= 0

奇怪的是,在isOptimal(...)方法的数组x中能得到预期的最优解值,但以下验证代码失败:

if (Math.abs(value - value1) > EPSILON || Math.abs(value - value2) > EPSILON) { 
    StdOut.println("value = " + value + ", cx = " + value1 + ", yb = " + value2); 
    return false;
}

原因是value2数值过大,导致abs(value - value2)超出EPSILON范围,不清楚为何会出现这种情况。

三、自定义变量选择策略对比

1. HighestFractionVariableSelectionStrategy

该策略能得到更优的目标函数值,且性能略优于后者:

public class HighestFractionVariableSelectionStrategy : IVariableSelectionStrategy
{
    private readonly FractionalPartComparer fractionalPartComparer;

    public HighestFractionVariableSelectionStrategy()
    {
        fractionalPartComparer = new FractionalPartComparer();
    }

    /// <inheritdoc />
    public int SelectVariable(double[] solutionValues)
    {
        if (solutionValues == null)
        {
            throw new ArgumentNullException(nameof(solutionValues));
        }

        // 过滤已为整数的变量
        var solutionForVariablesList = solutionValues.Where(x => (int)x != x).ToList();

        // 按小数部分从大到小排序
        solutionForVariablesList.Sort(fractionalPartComparer);


        // 如果至少有2个变量,选择整数部分更大的那个(比如7.5和6.8选7.5对应的变量)
        int indexOfSelectedVariable = -1;
        int value = -1;
        double[] solutionsSortedByHighestFraction = solutionForVariablesList.ToArray();
        if (solutionsSortedByHighestFraction.Length >= 2)
        {
            var valueVariable1 = (int)solutionsSortedByHighestFraction[0];
            var valueVariable2 = (int)solutionsSortedByHighestFraction[1];

            value = valueVariable1 > valueVariable2 ? valueVariable1 : valueVariable2;
        }
        else
        {
            value = (int)solutionsSortedByHighestFraction[0];
        }

        // 找到对应整数部分最大且小数部分最大的变量索引
        for (int i = 0; i < solutionValues.Length; i++)
        {
            if ((int)solutionValues[i] == value)
            {
                indexOfSelectedVariable = i;
                break;
            }
        }

        return indexOfSelectedVariable;
    }

    /// <summary>
    /// 按变量小数部分排序的比较器,小数部分越大排序越靠前
    /// </summary>
    private class FractionalPartComparer : Comparer<double>
    {
        public override int Compare(double value1, double value2)
        {
            double fractionalPart1 = value1 - Math.Floor(value1);
            double fractionalPart2 = value2 - Math.Floor(value2);

            if (fractionalPart1 > fractionalPart2) return -1;
            if (fractionalPart1 < fractionalPart2) return 1;

            return 0;
        }
    }
}

2. FarthestFromIntegerSelectionStrategy

该策略性能稍慢,得到的目标函数值优度更低:

public class FarthestFromIntegerSelectionStrategy : IVariableSelectionStrategy
{
    /// <inheritdoc />
    public int SelectVariable(double[] solutionValues)
    {
        if (solutionValues == null)
        {
            throw new ArgumentNullException(nameof(solutionValues));
        }

        var valueFarthestFromInteger = FindFarthestFromInteger(solutionValues);
        int index = Array.IndexOf(solutionValues, valueFarthestFromInteger);

        return index;
    }

    /// <summary>
    /// 找到数组中距离整数最远的值(最大不可行性规则,迫使分支树早期产生更大变化)
    /// </summary>
    /// <param name="values"></param>
    /// <returns></returns>
    private static double FindFarthestFromInteger(double[] values)
    {
        double farthest = values[0];
        double distance = Math.Abs(values[0] - Math.Round(values[0]));

        for (int i = 1; i < values.Length; i++)
        {
            double currentDistance = Math.Abs(values[i] - Math.Round(values[i]));

            if (currentDistance > distance)
            {
                distance = currentDistance;
                farthest = values[i];
            }
        }

        return farthest;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 07:57:41