在一个简单的 TSP 问题中消除子路径

问题描述

我正在尝试解决一个非常简单的 TSP 问题,但 SCIP 的 TSP 示例有点吓人。

我只想像 GuRoBi 那样添加简单的 Lazy 约束。

我可能需要一些帮助来了解某些地方正在发生的事情。

我假设我不必实现 SCIP_DECL_CONSSEPALP SCIP_DECL_CONSENFOLPSCIP_DECL_CONSENFOPS。我只需要实现一个简单的循环检测功能并将其添加一个剪辑。

如果我理解正确,我可以在 SCIP_DECL_CONSCHECK 中编写执行循环检测的函数,但我不确定它实际上是如何工作的。

assert(result != NULL);
   *result = SCIP_FEASIBLE;

   for( int i = 0; i < nconss; ++i )
   {
      SCIP_CONSDATA* consdata;
      GRAPH* graph;
      SCIP_Bool found;

      assert(conss != NULL);
      assert(conss[i] != NULL);
      consdata = SCIPconsGetData(conss[i]);
      assert(consdata != NULL);
      graph = consdata->graph;
      assert(graph != NULL);

      // if a subtour is found,the solution must be infeasible
      found = findSubtour(scip,graph,sol);
      if( found )
      {
         *result = SCIP_INFEASIBLE;
         if( printreason )
         {
            SCIP_CALL( SCIpprintCons(scip,conss[i],NULL) );
            SCIPinfoMessage(scip,NULL,"violation: graph has a subtour\n");
         }
      }
   }

   return SCIP_OKAY;

如果我只有一个约束处理程序,我还应该使用 nconss 吗? 找到子旅行后究竟会发生什么?将 *result 设置为 SCIP_INFEASIBLE调用哪个函数

我如何将在 SCIP_DECL_CONSCHECK 中找到的子环(环中的顶点)传递给该函数,以便我不必再次查找循环并添加实际切割?

解决方法

您实际上需要实现两个回调。 SCIP_DECL_CONSCHECKSCIP_DECL_CONSENFOLP

在检查回调中,您只需要检测是否找到了子游览,如果是,则将结果设置为 SCIP_INFEASIBLE(正如您所做的那样)。 您不必使用 nconss,因为您的 subtour 约束处理程序没有任何约束。

在执行回调 SCIP_DECL_CONSENFOLP 中,您必须通过添加新的子巡回消除约束来实际解决这些不可行性。

如果您想了解更多关于这些 SCIP 回调如何工作的信息,您可以听听我在去年 CO@Work 暑期学校的演讲(运行示例是 TSP)on youtube。 同一天的编程插件练习也是在 PySCIPopt 中实现 TSP,您可以在 Co@Work 网页上找到解决方案。