Visual c++ 为什么没有';NodeCallback中没有NodeID
我从BranchCallback获得了NodeID(getNodeID)和父级,并从NodeCallback获得了变量branch。当我绘制树搜索算法时,一些节点在这些节点之前没有任何变量分支,当我看到VS C++的控制台没有这些NoIDID的任何记录。但是我确信BranchCallback中有很多信息,比如这些节点的目标值。为什么呢?请注意(正如我在另一篇文章中解释的那样),控制台日志中显示的NodeID与回调中获得的NodeID不同。所以这两件事是不相关的 那么,对于你要问的其他问题,不清楚你是如何获得任何数据的。特别是,如果您在分支回调中收集节点,然后直到稍后才在节点回调中使用分支变量,那么这可能不适用于被修剪的节点。为什么不从分支回调中获取分支变量呢? 下面是一个简单的示例:Visual c++ 为什么没有';NodeCallback中没有NodeID,visual-c++,cplex,Visual C++,Cplex,我从BranchCallback获得了NodeID(getNodeID)和父级,并从NodeCallback获得了变量branch。当我绘制树搜索算法时,一些节点在这些节点之前没有任何变量分支,当我看到VS C++的控制台没有这些NoIDID的任何记录。但是我确信BranchCallback中有很多信息,比如这些节点的目标值。为什么呢?请注意(正如我在另一篇文章中解释的那样),控制台日志中显示的NodeID与回调中获得的NodeID不同。所以这两件事是不相关的 那么,对于你要问的其他问题,不清楚
#include <map>
#include <limits>
#include <iostream>
#include <ilcplex/ilocplex.h>
#include <ilconcert/ilothread.h>
using std::cout;
using std::endl;
/** The info we collect for a node. */
struct Info {
IloCplex::MIPCallbackI::NodeId id; /**< The node's id. */
IloCplex::MIPCallbackI::NodeId parent; /**< ID of the parent (root is 0). */
IloNumVar branchVar; /**< The variable on which CPLEX branched
* to create this node. */
IloNum branchVal; /**< The value CPLEX used for branching. */
IloCplex::BranchDirection branchDir; /**< The direction into which CPLEX branched. */
};
// Overload operator< so that we can use NodeIds as keys in maps.
bool operator<(IloCplex::MIPCallbackI::NodeId const &n1,
IloCplex::MIPCallbackI::NodeId const &n2)
{
return n1._id < n2._id;
}
// Map node ids to Info objects so that you can easily get from the info
// for a child to the info of its parent.
IloFastMutex lck;
typedef std::map<IloCplex::MIPCallbackI::NodeId,Info> MapType;
MapType nodeMap;
// A simple branch callback that tracks CPLEX branching decisions.
ILOBRANCHCALLBACK0(BranchCallback) {
IloInt const n = getNbranches();
IloCplex::MIPCallbackI::NodeId me = getNodeId();
IloNumVarArray x(getEnv());
IloNumArray bounds(getEnv());
IloCplex::BranchDirectionArray dirs(getEnv());
for (IloInt b = 0; b < n; ++b) {
// Get what CPLEX plans to do and perform the exact same branch.
// Then record all the information abouth the newly created branch.
getBranch(x, bounds, dirs, b);
Info info;
info.id = makeBranch(b);
info.parent = me;
if ( x.getSize() == 1 ) {
info.branchVar = x[0];
info.branchVal = bounds[0];
info.branchDir = dirs[0];
}
else {
// CPLEX branches on more than one variable. We don't record that.
info.branchVar = 0;
info.branchVal = std::numeric_limits<double>::quiet_NaN();
info.branchDir = IloCplex::BranchGlobal;
}
lck.lock();
nodeMap.insert(MapType::value_type(info.id, info));
lck.unlock();
}
dirs.end();
bounds.end();
x.end();
}
int
main(int argc, char **argv) {
for (int a = 1; a < argc; ++a) {
IloEnv env;
IloModel model(env);
IloCplex cplex(model);
cplex.importModel(model, argv[a]);
cplex.use(BranchCallback(env));
nodeMap.clear();
cplex.setParam(IloCplex::Threads, cplex.getNumCores());
//cplex.setParam(IloCplex::Threads, 1);
//cplex.setParam(IloCplex::NodeLim, 10);
cplex.solve();
// Print information about all the nodes.
for (MapType::const_iterator it = nodeMap.begin(); it != nodeMap.end(); ++it) {
Info const &i = it->second;
cout << "Node " << i.id << " created from " << i.parent
<< " by branching "
<< (i.branchDir == IloCplex::BranchUp ? "up" : "down")
<< " on " << (i.branchVar.getImpl() ? i.branchVar.getName() : "more than one variable")
<< " with value " << i.branchVal
<< endl;
}
env.end();
}
return 0;
}
转到Info
类并使用如下节点回调:
// A simple node callback that tracks the order in which nodes are selected.
ILONODECALLBACK0(NodeCallback) {
// The order that CPLEX plans to execute next is at index 0.
IloCplex::MIPCallbackI::NodeId next = getNodeId(0);
lck.lock();
static IloInt order = 0;
nodeMap[next].order = order++;
lck.unlock();
}
(您可以使用时间戳或其他东西来代替简单的计数器)。请注意(正如我在另一篇文章中解释的那样),控制台日志中显示的NodeID与回调中获得的NodeID不同。所以这两件事是不相关的
那么,对于你要问的其他问题,不清楚你是如何获得任何数据的。特别是,如果您在分支回调中收集节点,然后直到稍后才在节点回调中使用分支变量,那么这可能不适用于被修剪的节点。为什么不从分支回调中获取分支变量呢?
下面是一个简单的示例:
#include <map>
#include <limits>
#include <iostream>
#include <ilcplex/ilocplex.h>
#include <ilconcert/ilothread.h>
using std::cout;
using std::endl;
/** The info we collect for a node. */
struct Info {
IloCplex::MIPCallbackI::NodeId id; /**< The node's id. */
IloCplex::MIPCallbackI::NodeId parent; /**< ID of the parent (root is 0). */
IloNumVar branchVar; /**< The variable on which CPLEX branched
* to create this node. */
IloNum branchVal; /**< The value CPLEX used for branching. */
IloCplex::BranchDirection branchDir; /**< The direction into which CPLEX branched. */
};
// Overload operator< so that we can use NodeIds as keys in maps.
bool operator<(IloCplex::MIPCallbackI::NodeId const &n1,
IloCplex::MIPCallbackI::NodeId const &n2)
{
return n1._id < n2._id;
}
// Map node ids to Info objects so that you can easily get from the info
// for a child to the info of its parent.
IloFastMutex lck;
typedef std::map<IloCplex::MIPCallbackI::NodeId,Info> MapType;
MapType nodeMap;
// A simple branch callback that tracks CPLEX branching decisions.
ILOBRANCHCALLBACK0(BranchCallback) {
IloInt const n = getNbranches();
IloCplex::MIPCallbackI::NodeId me = getNodeId();
IloNumVarArray x(getEnv());
IloNumArray bounds(getEnv());
IloCplex::BranchDirectionArray dirs(getEnv());
for (IloInt b = 0; b < n; ++b) {
// Get what CPLEX plans to do and perform the exact same branch.
// Then record all the information abouth the newly created branch.
getBranch(x, bounds, dirs, b);
Info info;
info.id = makeBranch(b);
info.parent = me;
if ( x.getSize() == 1 ) {
info.branchVar = x[0];
info.branchVal = bounds[0];
info.branchDir = dirs[0];
}
else {
// CPLEX branches on more than one variable. We don't record that.
info.branchVar = 0;
info.branchVal = std::numeric_limits<double>::quiet_NaN();
info.branchDir = IloCplex::BranchGlobal;
}
lck.lock();
nodeMap.insert(MapType::value_type(info.id, info));
lck.unlock();
}
dirs.end();
bounds.end();
x.end();
}
int
main(int argc, char **argv) {
for (int a = 1; a < argc; ++a) {
IloEnv env;
IloModel model(env);
IloCplex cplex(model);
cplex.importModel(model, argv[a]);
cplex.use(BranchCallback(env));
nodeMap.clear();
cplex.setParam(IloCplex::Threads, cplex.getNumCores());
//cplex.setParam(IloCplex::Threads, 1);
//cplex.setParam(IloCplex::NodeLim, 10);
cplex.solve();
// Print information about all the nodes.
for (MapType::const_iterator it = nodeMap.begin(); it != nodeMap.end(); ++it) {
Info const &i = it->second;
cout << "Node " << i.id << " created from " << i.parent
<< " by branching "
<< (i.branchDir == IloCplex::BranchUp ? "up" : "down")
<< " on " << (i.branchVar.getImpl() ? i.branchVar.getName() : "more than one variable")
<< " with value " << i.branchVal
<< endl;
}
env.end();
}
return 0;
}
转到Info
类并使用如下节点回调:
// A simple node callback that tracks the order in which nodes are selected.
ILONODECALLBACK0(NodeCallback) {
// The order that CPLEX plans to execute next is at index 0.
IloCplex::MIPCallbackI::NodeId next = getNodeId(0);
lck.lock();
static IloInt order = 0;
nodeMap[next].order = order++;
lck.unlock();
}
(您可以使用时间戳或其他东西,而不是简单的计数器)。不清楚您在问什么,以及如何获得所拥有的信息。你能展示你代码的所有相关部分吗?你是如何准确地获得你所拥有的所有信息的,以及你是如何将不同的信息联系起来的。目前还不清楚你在问什么以及你是如何获得你所拥有的信息的。你能展示你代码的所有相关部分吗?您如何准确地获取所有信息,以及如何将不同的信息联系起来。