Вы спрашиваете много вещей одновременно. Я собираюсь ответить на вопрос, который связан с предметом. Для всего остального, пожалуйста, создайте новый вопрос и покажите ваш код, ваш фактический результат и объясните, чем он отличается от ожидаемого результата.
Класс IloCplex имеет функцию out () . Эта функция возвращает ссылку на поток, в который CPLEX отправляет все свои выходные данные. Вы можете передать эту ссылку своим обратным вызовам, а затем записать в этот поток свои обратные вызовы.
Например:
ILOUSERCUTCALLBACK1(MyCallback, std::ostream &, output) {
output << "Message from callback" << std::endl;
}
, а затем
cplex.use(MyCallback(cplex.getEnv(), cplex.out()));
для создания и регистрации обратного вызова.
ОБНОВЛЕНИЕ После того, как вы отредактировали свой вопрос, кажется, что ваша проблема не в том, чтобы напечатать вывод из обратного вызова, а что-то еще.
Прежде всего, обратите внимание, что ожидается получение разных путей поиска, если вы выполните один запуск с обратным вызовом пользователя, сокращенным, а другой - с обратным вызовом ветви. Невозможно связать номера узлов или идентификаторы узлов от одного прогона к другому. Статистику, которую вы хотите получить, необходимо получить с помощью один прогон .
Кроме того, для идентификации узла не следует использовать номер узла или количество обработанных узлов (число в самом левом столбце в журнале). Вместо этого вы должны использовать идентификатор узла. Это то, что известно как порядковый номер в C ++ API. Это only вещь, которую вы можете использовать для идентификации узла. Эти идентификаторы должны совпадать с идентификаторами узлов, показанными в правой части журнала, в случае, если динамический поиск отключен (что происходит автоматически, если вы используете контрольные обратные вызовы). Эти идентификаторы узлов доступны во всех обратных вызовах, и вы можете использовать их для сбора информации, собранной из различных обратных вызовов для одного и того же узла.
Обновление 2 : На самом деле я был не прав. Число, возвращаемое getNodeId()
, и число, указанное в столбце NodeID
журнала, отличаются, см. Мой ответ на на этот вопрос . Нет никакого способа связать эти два числа. Извините за путаницу. Я думаю, что вы задавали подобный вопрос и на другом форуме, и я утверждал, что эти два числа совпадают. Это тоже было неправильно. Снова извините.
Так что, по сути, ваш единственный способ связать вещи в обратном вызове с вещами в журнале - это выполнить однопоточный прогон, а затем посмотреть порядок, в котором печатаются вещи.
Однако, чтобы отследить дерево (наряду с псевдо-стоимостью и т. Д.), Вам не нужен журнал. Вы можете сделать все от обратного вызова, просто используя порядковые номера. Самая сложная часть - это отслеживание родительско-дочерних отношений, что можно сделать так (не то, что это не поточно-безопасный):
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());
}
}