如何在C ++ / CPLEX中集成回调的输出

时间:2019-07-11 06:26:31

标签: visual-c++ cplex

我在代码中使用了宏回调,并且希望将输出集成在一起。在每个节点上,我都需要Pseudocosts,slacks,variableBranch等的值。但是我不知道如何集成通过不同的Callback检索到的这些数据。我不会一起运行所有回调。每次我使用不同的回调运行代码时,NodeID或Node的值都不相等。例如,在pic1中,我运行BranchCallback来检索伪成本,而在pic3中,我使用UserCutCallback来检索每个节点上的变量值。从pic1中可以看到,最后一个节点是126,而在pic3中,最后一个节点是164。我想在excel中为每个节点创建数据结构,但是我不知道我必须考虑的节点数是126还是164? 例如在pic1中,我可以说所有有关node10的信息(伪成本值)都属于pic3中的node10吗?在pic3中,有关node10的所有信息(slacks的值)是否都属于pic1中的node10?

ILOUSERCUTCALLBACK1(Myvalue, IloArray<IloNumVarArray>, vars) {
for (int i = 0; i < nbworkers; ++i) {
for (int j = 0; j < nbmachines; j++) {
cout << "getvalue(" << vars[i][j] << ") = "
<< getValue(vars[i][j]) << endl;
}
}
}

enter image description here enter image description here

1 个答案:

答案 0 :(得分:3)

您同时问许多事情。我将回答与该主题有关的问题。对于其他所有内容,请创建一个新问题,并显示您的代码,实际输出并说明与预期输出有何不同。

IloCplex类具有函数out()。该函数返回对CPLEX将其所有输出发送到的流的引用。您可以将该引用传递给回调,然后从回调中写入该流。

例如:

ILOUSERCUTCALLBACK1(MyCallback, std::ostream &, output) {
  output << "Message from callback" << std::endl;
}

然后

cplex.use(MyCallback(cplex.getEnv(), cplex.out()));

创建和注册回调。

更新,在您编辑问题之后,看来您的问题不是打印回调的输出,而是打印其他内容。

首先请注意,如果一次使用用户剪切回调运行而另一次使用分支回调运行,则有望获得不同的搜索路径。无法将一次运行的节点号或节点ID与另一次运行相关联。您要获取的统计信息必须通过单次运行获取。

此外,为了标识一个节点,您不应使用该节点号或已处理的节点数(日志中最左边一栏中的数字)。相反,您应该使用节点的ID。这就是C ++ API中的序列号。这是 only 可以用来标识节点的东西。如果禁用了动态搜索(如果使用控件回调,则会自动发生),这些ID应与日志最右边显示的节点ID相匹配。这些节点ID可从所有回调中获得,您可以使用它们来收集从同一节点的不同回调中收集的信息。

更新2 :其实我错了。 getNodeId()返回的数字和日志的NodeID列中显示的数字是不同的,请参阅我对this question的回答。没有办法将这两个数字联系起来。对困惑感到抱歉。我想您也在另一个论坛上也提出了类似的问题,我声称这两个数字是相同的。那也是错的。再次抱歉。

因此,基本上,将回调中的内容与日志中的内容相关联的唯一选择是执行单线程运行,然后查看打印顺序。

但是,为了跟踪树(以及伪成本等),您不需要日志。您只需使用序列号就可以完成回调中的所有操作。最困难的部分是跟踪父/子关系,这可以通过以下方式完成(并非这不是 线程安全的):

struct Parent {
   typedef IloCplex::MIPCallbackI::NodeId NodeId;
   struct Less {
      bool operator()(NodeId const &n1, NodeId const &n2) const {
         return n1._id < n2._id;
      }
   };
   typedef std::map<NodeId,NodeId,Less> MapType;
   MapType parents;
   void set(NodeId child, NodeId parent) { parents[child] = parent; }
   IloCplex::MIPCallbackI::NodeId get(NodeId child) const {
      MapType::const_iterator it = parents.find(child);
      return (it == parents.end()) ? NodeId() : it->second;
   }
};

Parent parent;

ILOBRANCHCALLBACK0(BranchCallback) {
   std::cout << "CALLBACK[B]: " << getNodeId()
             << " (" << parent.get(getNodeId()) << ")" << std::endl;
   int const n = getNbranches();
   for (int i = 0; i < n; ++i) {
      NodeId id = makeBranch(i);
      parent.set(id, getNodeId());
   }
}