基于线性规划的图Steiner树问题的分支切割法求解示例
字数 4657 2025-12-15 01:20:40

基于线性规划的图Steiner树问题的分支切割法求解示例

我将为您讲解图Steiner树问题的一个分支切割法求解示例,这个问题是经典的组合优化问题,在通信网络设计等领域有重要应用。


问题描述:Steiner树问题

问题背景:
给定一个无向连通图 \(G=(V,E)\),其中 \(V\) 是顶点集,\(E\) 是边集,每条边 \(e \in E\) 有一个非负费用 \(c_e\)。同时给定一个终端顶点集合 \(T \subseteq V\)(称为Steiner点集),要求找到一个包含 \(T\) 中所有顶点的连通子图,且总边费用最小。这个子图必然是一棵树(称为Steiner树),它可以包含非终端顶点(称为Steiner顶点)来减少总费用。

难点:
这是一个NP难问题。当 \(T = V\) 时,退化为最小生成树问题,可在多项式时间内求解。但当 \(T \subset V\) 时,寻找最优解是困难的。

整数规划模型:
我们采用基于割的模型。定义决策变量 \(x_e \in \{0,1\}\),表示边 \(e\) 是否被选中。

目标函数:最小化总费用

\[\min \sum_{e \in E} c_e x_e \]

约束条件:

  1. 连通性约束:对于任意割 \((S, V \setminus S)\) 使得 \(S \cap T \neq \emptyset\)\((V \setminus S) \cap T \neq \emptyset\)(即割分离了至少两个终端顶点),被选边集必须跨越该割至少一次。

\[\sum_{e \in \delta(S)} x_e \ge 1 \quad \forall S \subset V: S \cap T \neq \emptyset, T \setminus S \neq \emptyset \]

其中 \(\delta(S)\) 表示一个端点属于 \(S\)、另一个端点不属于 \(S\) 的边集。

  1. 整数性约束

\[x_e \in \{0,1\} \quad \forall e \in E \]

这个模型有指数数量的约束(每个合法割对应一个约束),因此无法直接列出所有约束求解。


解题过程:分支切割法

我们使用分支切割法(Branch-and-Cut),它结合了分支定界和割平面法。核心思想:在分支定界树的每个节点,求解线性规划松弛(可能加入部分割约束),然后检查当前分数解是否违反未加入的割约束;若是,则找到相应的割平面加入线性规划,重新求解;重复直至解满足所有割约束或确定加入足够割平面,再进行分支。

步骤1:初始化线性规划松弛
初始松弛仅包含度约束(可选,可加快收敛)和变量边界。

  • 目标函数:\(\min \sum_{e \in E} c_e x_e\)
  • 约束:

\[ 0 \le x_e \le 1 \quad \forall e \in E \]

通常还会加入:对于每个终端顶点 \(v \in T\),其关联边被选数量至少为1(除非 \(|T|=1\)):

\[ \sum_{e \in \delta(\{v\})} x_e \ge 1 \quad \forall v \in T \]

但这不保证全局连通性,所以后续需要割平面。

初始松弛最优解可能是全0或某些边选一小部分分数,显然不满足连通性。

步骤2:割平面生成(分离问题)
求解当前线性规划得到分数解 \(x^*\)。我们需要检查是否存在被违反的割约束,即是否存在 \(S\) 使得:

\[\sum_{e \in \delta(S)} x_e^* < 1 \]

\(S \cap T \neq \emptyset\), \(T \setminus S \neq \emptyset\)

这等价于:在当前图 \(G\) 上,边权为 \(x_e^*\),寻找一个最小容量的割 \((S, V \setminus S)\) 满足 \(S\) 分离了 \(T\)。若该最小割容量 \(< 1\),则对应约束被违反。

分离算法

  1. 固定一个终端顶点 \(r \in T\) 作为根。
  2. 对于每个其他终端顶点 \(t \in T \setminus \{r\}\)
    • 计算从 \(r\)\(t\) 在边权 \(x^*\) 下的最大流(最小割)。
    • 若最大流值 \(< 1\),则得到被违反的割 \(S\)(包含 \(r\) 的割集),加入割平面:

\[ \sum_{e \in \delta(S)} x_e \ge 1 \]

  1. 由于对称性,通常检查所有终端对 \((r,t)\) 即可保证找到所有被违反的割(实践中也可随机选根,或检查几个根)。

加入割平面后,重新求解线性规划。

步骤3:迭代割平面加入
重复步骤2,直至对每个终端对 \((r,t)\),最大流值均 \(\ge 1\)。此时分数解 \(x^*\) 满足所有连通性约束(实际是满足所有终端对之间的最小割至少为1,这等价于全局连通性),得到一个可行的线性规划松弛解,其目标值是原问题最优值的下界。

步骤4:分支定界
若此时所有 \(x_e^*\) 都是整数(0或1),则得到整数最优解,算法结束。否则,选择某个分数变量 \(x_e\)(例如最接近0.5的),进行分支:

  • 左分支:强制 \(x_e = 0\)
  • 右分支:强制 \(x_e = 1\)

对每个子节点,重复步骤1-3(求解线性规划松弛并加入割平面),得到该节点的下界。如果某个节点的下界超过当前已知整数解的上界,则剪枝。如果得到整数解,则更新上界。

继续分支,直至所有节点处理完毕,此时得到最优解。


示例演示

考虑一个小型图示例:

  • 顶点:\(V = \{1,2,3,4\}\)
  • 边及费用:
    \(e_{12}: c=3\)
    \(e_{13}: c=4\)
    \(e_{14}: c=5\)
    \(e_{23}: c=2\)
    \(e_{24}: c=3\)
    \(e_{34}: c=1\)
  • 终端顶点集:\(T = \{1,2,3\}\)(顶点4是潜在的Steiner顶点)

步骤1:初始松弛
初始线性规划:

\[\min 3x_{12} + 4x_{13} + 5x_{14} + 2x_{23} + 3x_{24} + x_{34} \]

s.t.

\[0 \le x_e \le 1 \quad \forall e \]

加上终端度约束(可选):

\[x_{12}+x_{13}+x_{14} \ge 1 \]

\[ x_{12}+x_{23}+x_{24} \ge 1 \]

\[ x_{13}+x_{23}+x_{34} \ge 1 \]

求解得:\(x_{12}=0.5, x_{13}=0.5, x_{23}=0.5\),其他为0,目标值=4.5。

步骤2:割平面分离
选择根 \(r=1\),检查终端对 (1,2):

  • 边权 \(x^*\) 下,从1到2的最大流路径:1→2直接容量0.5,1→3→2容量 min(0.5,0.5)=0.5,总最大流=1.0(等于1,不违反)。
    检查 (1,3):
  • 1→3直接容量0.5,1→2→3容量 min(0.5,0.5)=0.5,总最大流=1.0。
    因此当前解满足所有终端对割约束,无需加割。

但解是分数,需要分支。

步骤3:分支
选择 \(x_{12}\)(值为0.5)分支。

左分支:\(x_{12}=0\)
求解线性规划(加上 \(x_{12}=0\)),得:
\(x_{13}=0.5, x_{23}=0.5, x_{34}=0.5\),其他为0,目标值=3.5。
检查割:根 r=1,对终端2:1→3→2路径容量 min(0.5,0.5)=0.5,无其他路径,最大流=0.5 < 1,违反。
对应的割 S={1,3,4}(从1可达的点集),加入割:

\[x_{13}+x_{14}+x_{34} \ge 1 \]

重新求解,得:\(x_{13}=0.5, x_{23}=0.5, x_{34}=0.5\) 仍满足新约束(左端=0.5+0+0.5=1)。继续检查其他终端对,无违反。目标值=3.5。
解仍分数,可继续分支(但先看右分支)。

右分支:\(x_{12}=1\)
求解线性规划(加上 \(x_{12}=1\)),得:
\(x_{12}=1, x_{23}=0, x_{13}=0, x_{34}=1, x_{14}=0, x_{24}=0\),目标值=3+1=4。
检查所有终端对连通性:

  • 1到2:直接边,满足。
  • 1到3:路径1→2→? 无,但1→? 可通过1→? 不直接;实际上,1通过边12到2,但2到3无边,且2到4无边,4到3有边x34=1,但1到4无边。因此1和3不连通!这意味着需要检查割。
    计算从1到3的最大流:在分数解中,1→2容量1,但2→3容量0,2→4容量0,所以从1无法到3,最大流=0,违反。
    对应割 S={1,2},加入割:

\[x_{13}+x_{14}+x_{23}+x_{24} \ge 1 \]

重新求解,得:\(x_{12}=1, x_{34}=1, x_{23}=0, x_{13}=0, x_{14}=0, x_{24}=0\) 不满足新约束(左端=0),需调整。
求解后得新解:\(x_{12}=1, x_{23}=1, x_{34}=0\),其他为0,目标值=3+2=5。
检查连通性:此时1-2-3连通,但终端集T={1,2,3}已连通,所以是可行整数解(Steiner树为边12和23),费用=5。

步骤4:回溯与比较
左分支下界=3.5,右分支整数解=5。全局上界=5。
继续分支左分支(下界3.5),可能得到更优解。若在左分支继续分支并找到整数解,比如选择 \(x_{13}\) 分支,可能得到树 {13,23} 费用=6,或树 {13,34,12?} 等。最终搜索得到最优解可能是 {23,34,13}? 但费用=2+1+4=7,不如5。实际上,枚举可知最优Steiner树为 {12,23} 费用5,或 {12,24,34,13}? 包含Steiner顶点4的树 {12,24,34} 费用=3+3+1=7 更差。但本例中,Steiner顶点4并未帮助减少费用。

因此最优解为边 {12,23},总费用=5。


总结

分支切割法通过动态加入割平面来强化线性规划松弛,从而获得紧的下界,并结合分支定界搜索整数解。对于Steiner树问题,割平面分离转化为最大流问题,可在多项式时间内完成,这使得该方法能够处理中等规模的问题实例。在实际软件(如ILOG CPLEX、SCIP)中,这些过程已自动化,用户只需定义模型,求解器会自动处理分支切割。

基于线性规划的图Steiner树问题的分支切割法求解示例 我将为您讲解图Steiner树问题的一个分支切割法求解示例,这个问题是经典的组合优化问题,在通信网络设计等领域有重要应用。 问题描述:Steiner树问题 问题背景: 给定一个无向连通图 \( G=(V,E) \),其中 \( V \) 是顶点集,\( E \) 是边集,每条边 \( e \in E \) 有一个非负费用 \( c_ e \)。同时给定一个终端顶点集合 \( T \subseteq V \)(称为Steiner点集),要求找到一个包含 \( T \) 中所有顶点的连通子图,且总边费用最小。这个子图必然是一棵树(称为Steiner树),它可以包含非终端顶点(称为Steiner顶点)来减少总费用。 难点: 这是一个NP难问题。当 \( T = V \) 时,退化为最小生成树问题,可在多项式时间内求解。但当 \( T \subset V \) 时,寻找最优解是困难的。 整数规划模型: 我们采用基于割的模型。定义决策变量 \( x_ e \in \{0,1\} \),表示边 \( e \) 是否被选中。 目标函数:最小化总费用 \[ \min \sum_ {e \in E} c_ e x_ e \] 约束条件: 连通性约束 :对于任意割 \( (S, V \setminus S) \) 使得 \( S \cap T \neq \emptyset \) 且 \( (V \setminus S) \cap T \neq \emptyset \)(即割分离了至少两个终端顶点),被选边集必须跨越该割至少一次。 \[ \sum_ {e \in \delta(S)} x_ e \ge 1 \quad \forall S \subset V: S \cap T \neq \emptyset, T \setminus S \neq \emptyset \] 其中 \( \delta(S) \) 表示一个端点属于 \( S \)、另一个端点不属于 \( S \) 的边集。 整数性约束 : \[ x_ e \in \{0,1\} \quad \forall e \in E \] 这个模型有指数数量的约束(每个合法割对应一个约束),因此无法直接列出所有约束求解。 解题过程:分支切割法 我们使用分支切割法(Branch-and-Cut),它结合了分支定界和割平面法。核心思想:在分支定界树的每个节点,求解线性规划松弛(可能加入部分割约束),然后检查当前分数解是否违反未加入的割约束;若是,则找到相应的割平面加入线性规划,重新求解;重复直至解满足所有割约束或确定加入足够割平面,再进行分支。 步骤1:初始化线性规划松弛 初始松弛仅包含度约束(可选,可加快收敛)和变量边界。 目标函数:\( \min \sum_ {e \in E} c_ e x_ e \) 约束: \[ 0 \le x_ e \le 1 \quad \forall e \in E \] 通常还会加入:对于每个终端顶点 \( v \in T \),其关联边被选数量至少为1(除非 \( |T|=1 \)): \[ \sum_ {e \in \delta(\{v\})} x_ e \ge 1 \quad \forall v \in T \] 但这不保证全局连通性,所以后续需要割平面。 初始松弛最优解可能是全0或某些边选一小部分分数,显然不满足连通性。 步骤2:割平面生成(分离问题) 求解当前线性规划得到分数解 \( x^* \)。我们需要检查是否存在被违反的割约束,即是否存在 \( S \) 使得: \[ \sum_ {e \in \delta(S)} x_ e^* < 1 \] 且 \( S \cap T \neq \emptyset \), \( T \setminus S \neq \emptyset \)。 这等价于:在当前图 \( G \) 上,边权为 \( x_ e^* \),寻找一个最小容量的割 \( (S, V \setminus S) \) 满足 \( S \) 分离了 \( T \)。若该最小割容量 \( < 1 \),则对应约束被违反。 分离算法 : 固定一个终端顶点 \( r \in T \) 作为根。 对于每个其他终端顶点 \( t \in T \setminus \{r\} \): 计算从 \( r \) 到 \( t \) 在边权 \( x^* \) 下的最大流(最小割)。 若最大流值 \( < 1 \),则得到被违反的割 \( S \)(包含 \( r \) 的割集),加入割平面: \[ \sum_ {e \in \delta(S)} x_ e \ge 1 \] 由于对称性,通常检查所有终端对 \( (r,t) \) 即可保证找到所有被违反的割(实践中也可随机选根,或检查几个根)。 加入割平面后,重新求解线性规划。 步骤3:迭代割平面加入 重复步骤2,直至对每个终端对 \( (r,t) \),最大流值均 \( \ge 1 \)。此时分数解 \( x^* \) 满足所有连通性约束(实际是满足所有终端对之间的最小割至少为1,这等价于全局连通性),得到一个可行的线性规划松弛解,其目标值是原问题最优值的下界。 步骤4:分支定界 若此时所有 \( x_ e^* \) 都是整数(0或1),则得到整数最优解,算法结束。否则,选择某个分数变量 \( x_ e \)(例如最接近0.5的),进行分支: 左分支:强制 \( x_ e = 0 \) 右分支:强制 \( x_ e = 1 \) 对每个子节点,重复步骤1-3(求解线性规划松弛并加入割平面),得到该节点的下界。如果某个节点的下界超过当前已知整数解的上界,则剪枝。如果得到整数解,则更新上界。 继续分支,直至所有节点处理完毕,此时得到最优解。 示例演示 考虑一个小型图示例: 顶点:\( V = \{1,2,3,4\} \) 边及费用: \( e_ {12}: c=3 \) \( e_ {13}: c=4 \) \( e_ {14}: c=5 \) \( e_ {23}: c=2 \) \( e_ {24}: c=3 \) \( e_ {34}: c=1 \) 终端顶点集:\( T = \{1,2,3\} \)(顶点4是潜在的Steiner顶点) 步骤1:初始松弛 初始线性规划: \[ \min 3x_ {12} + 4x_ {13} + 5x_ {14} + 2x_ {23} + 3x_ {24} + x_ {34} \] s.t. \[ 0 \le x_ e \le 1 \quad \forall e \] 加上终端度约束(可选): \[ x_ {12}+x_ {13}+x_ {14} \ge 1 \] \[ x_ {12}+x_ {23}+x_ {24} \ge 1 \] \[ x_ {13}+x_ {23}+x_ {34} \ge 1 \] 求解得:\( x_ {12}=0.5, x_ {13}=0.5, x_ {23}=0.5 \),其他为0,目标值=4.5。 步骤2:割平面分离 选择根 \( r=1 \),检查终端对 (1,2): 边权 \( x^* \) 下,从1到2的最大流路径:1→2直接容量0.5,1→3→2容量 min(0.5,0.5)=0.5,总最大流=1.0(等于1,不违反)。 检查 (1,3): 1→3直接容量0.5,1→2→3容量 min(0.5,0.5)=0.5,总最大流=1.0。 因此当前解满足所有终端对割约束,无需加割。 但解是分数,需要分支。 步骤3:分支 选择 \( x_ {12} \)(值为0.5)分支。 左分支:\( x_ {12}=0 \) 求解线性规划(加上 \( x_ {12}=0 \)),得: \( x_ {13}=0.5, x_ {23}=0.5, x_ {34}=0.5 \),其他为0,目标值=3.5。 检查割:根 r=1,对终端2:1→3→2路径容量 min(0.5,0.5)=0.5,无其他路径,最大流=0.5 < 1,违反。 对应的割 S={1,3,4}(从1可达的点集),加入割: \[ x_ {13}+x_ {14}+x_ {34} \ge 1 \] 重新求解,得:\( x_ {13}=0.5, x_ {23}=0.5, x_ {34}=0.5 \) 仍满足新约束(左端=0.5+0+0.5=1)。继续检查其他终端对,无违反。目标值=3.5。 解仍分数,可继续分支(但先看右分支)。 右分支:\( x_ {12}=1 \) 求解线性规划(加上 \( x_ {12}=1 \)),得: \( x_ {12}=1, x_ {23}=0, x_ {13}=0, x_ {34}=1, x_ {14}=0, x_ {24}=0 \),目标值=3+1=4。 检查所有终端对连通性: 1到2:直接边,满足。 1到3:路径1→2→? 无,但1→? 可通过1→? 不直接;实际上,1通过边12到2,但2到3无边,且2到4无边,4到3有边x34=1,但1到4无边。因此1和3不连通!这意味着需要检查割。 计算从1到3的最大流:在分数解中,1→2容量1,但2→3容量0,2→4容量0,所以从1无法到3,最大流=0,违反。 对应割 S={1,2},加入割: \[ x_ {13}+x_ {14}+x_ {23}+x_ {24} \ge 1 \] 重新求解,得:\( x_ {12}=1, x_ {34}=1, x_ {23}=0, x_ {13}=0, x_ {14}=0, x_ {24}=0 \) 不满足新约束(左端=0),需调整。 求解后得新解:\( x_ {12}=1, x_ {23}=1, x_ {34}=0 \),其他为0,目标值=3+2=5。 检查连通性:此时1-2-3连通,但终端集T={1,2,3}已连通,所以是可行整数解(Steiner树为边12和23),费用=5。 步骤4:回溯与比较 左分支下界=3.5,右分支整数解=5。全局上界=5。 继续分支左分支(下界3.5),可能得到更优解。若在左分支继续分支并找到整数解,比如选择 \( x_ {13} \) 分支,可能得到树 {13,23} 费用=6,或树 {13,34,12?} 等。最终搜索得到最优解可能是 {23,34,13}? 但费用=2+1+4=7,不如5。实际上,枚举可知最优Steiner树为 {12,23} 费用5,或 {12,24,34,13}? 包含Steiner顶点4的树 {12,24,34} 费用=3+3+1=7 更差。但本例中,Steiner顶点4并未帮助减少费用。 因此最优解为边 {12,23},总费用=5。 总结 分支切割法通过动态加入割平面来强化线性规划松弛,从而获得紧的下界,并结合分支定界搜索整数解。对于Steiner树问题,割平面分离转化为最大流问题,可在多项式时间内完成,这使得该方法能够处理中等规模的问题实例。在实际软件(如ILOG CPLEX、SCIP)中,这些过程已自动化,用户只需定义模型,求解器会自动处理分支切割。